<commit_before>/*
 * Copyright (C) 2015 Fondazione Istituto Italiano di Tecnologia
 * Authors: Silvio Traversaro
 * CopyPolicy: Released under the terms of the LGPLv2.1 or later, see LGPL.TXT
 *
 */

#include "testModels.h"

#include <iDynTree/HighLevel/DynamicsComputations.h>

#include <iDynTree/Core/MatrixDynSize.h>
#include <iDynTree/Core/Transform.h>
#include <iDynTree/Core/Twist.h>
#include <iDynTree/Core/SpatialAcc.h>
#include <iDynTree/Core/ClassicalAcc.h>
#include <iDynTree/Core/VectorDynSize.h>
#include <iDynTree/Core/Utils.h>
#include <iDynTree/Core/TestUtils.h>
#include <iDynTree/Core/Wrench.h>

#include <iDynTree/Core/EigenHelpers.h>

using namespace iDynTree;

//void checkStateIsDefaultOne(DynamicsComputations & dynComp)
//{
//    dynComp.getStat

//    ASSERT_EQUAL_TRANSFORM(notRotated_H_rotated,);
//}

double random_double()
{
    return ((double)rand()-RAND_MAX/2)/((double)RAND_MAX);
}

void setRandomState(iDynTree::HighLevel::DynamicsComputations & dynComp)
{
    size_t dofs = dynComp.getNrOfDegreesOfFreedom();
    Transform    worldTbase;
    Twist        baseVel;
    ClassicalAcc baseAcc;
    SpatialAcc gravity;
    Vector6    properAcc;

    iDynTree::VectorDynSize qj(dofs), dqj(dofs), ddqj(dofs);

    worldTbase = //iDynTree::Transform::Identity();
    iDynTree::Transform(Rotation::RPY(random_double(),random_double(),random_double()),
            Position(random_double(),random_double(),random_double()));

    for(int i=0; i < 3; i++)
    {
        gravity(i) = random_double();
    }

    gravity(2) = 10.0;

    for(int i=0; i < 6; i++)
    {
        baseVel(i) = random_double();
        baseAcc(i) = random_double();
        properAcc(i) = baseAcc(i) + gravity(i);
    }

    for(size_t dof=0; dof < dofs; dof++)

    {
        qj(dof) = random_double();
        dqj(dof) = random_double();
        ddqj(dof) = random_double();
    }

    bool ok = dynComp.setRobotState(qj,dqj,ddqj,worldTbase,baseVel,baseAcc,gravity);

    ASSERT_EQUAL_DOUBLE(ok,true);
}

void testJacobianVsForwardKinematicsConsistency(iDynTree::HighLevel::DynamicsComputations & dynComp)
{
    size_t dofs = dynComp.getNrOfDegreesOfFreedom();
    size_t frames = dynComp.getNrOfFrames();

    MatrixDynSize jac(6,6+dofs);
    Eigen::VectorXd robotVel(6+dofs);

    Vector6 velBaseTwist = dynComp.getBaseTwist().asVector();
    robotVel.segment(0,6) = toEigen(velBaseTwist);
    VectorDynSize jointVel(dofs);
    dynComp.getJointVel(jointVel);
    robotVel.segment(6,dofs) = toEigen(jointVel);

    Twist velFromJac, velFromFwdKin;

    for(size_t frame=0; frame < frames; frame++)
    {
        velFromFwdKin = dynComp.getFrameTwistInWorldOrient(frame);
        dynComp.getFrameJacobian(frame,jac);

        Eigen::Matrix<double,6,1> velJac = toEigen(jac)*robotVel;

        toEigen(velFromJac.getLinearVec3()) = velJac.segment<3>(0);
        toEigen(velFromJac.getAngularVec3()) = velJac.segment<3>(3);
    }

    ASSERT_EQUAL_VECTOR(velFromFwdKin.asVector(),velFromJac.asVector());
}

void testRegressorVsInverseDynamicsConsistency(iDynTree::HighLevel::DynamicsComputations & dynComp)
{
    size_t dofs = dynComp.getNrOfDegreesOfFreedom();
    size_t nrOfLinks = dynComp.getNrOfLinks();

    // check regressor matrix
    MatrixDynSize dynRegressor(6+dofs,10*nrOfLinks);
    dynComp.getDynamicsRegressor(dynRegressor);

    // check parameter vector
    VectorDynSize dynParams(10*nrOfLinks);
    dynComp.getModelDynamicsParameters(dynParams);

    // compute inverseDynamics with regressor
    VectorDynSize idResultRegr(6+dofs), torquesRegr(dofs), torquesID(dofs);
    Wrench baseWrenchID, baseWrenchRegr;
    toEigen(idResultRegr) = toEigen(dynRegressor)*toEigen(dynParams);

    toEigen(baseWrenchRegr.getLinearVec3()) = toEigen(idResultRegr).segment(0,3);
    toEigen(baseWrenchRegr.getAngularVec3()) = toEigen(idResultRegr).segment(3,3);

    toEigen(torquesRegr)    = toEigen(idResultRegr).segment(6,dofs);

    // compute inverseDynam
    dynComp.inverseDynamics(torquesID,baseWrenchID);

    ASSERT_EQUAL_VECTOR(torquesID,torquesRegr);
    ASSERT_EQUAL_VECTOR(baseWrenchID,baseWrenchRegr);
}

void testModelConsistency(std::string modelFilePath)
{
    HighLevel::DynamicsComputations dynComp;

    bool ok = dynComp.loadRobotModelFromFile(modelFilePath);

    setRandomState(dynComp);

    testJacobianVsForwardKinematicsConsistency(dynComp);
    testRegressorVsInverseDynamicsConsistency(dynComp);
}

void testTwoLinksRotationOnZAxisRegressor()
{
    std::string urdfFileName = getAbsModelPath("twoLinksRotationOnZAxis.urdf");
    HighLevel::DynamicsComputations dynComp;
    bool ok = dynComp.loadRobotModelFromFile(urdfFileName);
    ASSERT_IS_TRUE(ok);

    setRandomState(dynComp);

    MatrixDynSize regr;
    ok = dynComp.getDynamicsRegressor(regr);
    ASSERT_IS_TRUE(ok);
    std::cerr << regr.toString() << std::endl;
}

int main()
{
    for(unsigned int mdl = 0; mdl < IDYNTREE_TESTS_URDFS_NR; mdl++ )
    {
        std::string urdfFileName = getAbsModelPath(std::string(IDYNTREE_TESTS_URDFS[mdl]));
        std::cout << "Testing file " << std::string(IDYNTREE_TESTS_URDFS[mdl]) <<  std::endl;
        testModelConsistency(urdfFileName);
    }

    // Do a special test for the regression on a model that just has 1 joint that rotates
    // around the Z axis, and both link frames have the origin on that axes
    testTwoLinksRotationOnZAxisRegressor();

    return EXIT_SUCCESS;
}
<commit_msg>Remove not initialized memory in DynamicsComputationsUnitTest<commit_after>/*
 * Copyright (C) 2015 Fondazione Istituto Italiano di Tecnologia
 * Authors: Silvio Traversaro
 * CopyPolicy: Released under the terms of the LGPLv2.1 or later, see LGPL.TXT
 *
 */

#include "testModels.h"

#include <iDynTree/HighLevel/DynamicsComputations.h>

#include <iDynTree/Core/MatrixDynSize.h>
#include <iDynTree/Core/Transform.h>
#include <iDynTree/Core/Twist.h>
#include <iDynTree/Core/SpatialAcc.h>
#include <iDynTree/Core/ClassicalAcc.h>
#include <iDynTree/Core/VectorDynSize.h>
#include <iDynTree/Core/Utils.h>
#include <iDynTree/Core/TestUtils.h>
#include <iDynTree/Core/Wrench.h>

#include <iDynTree/Core/EigenHelpers.h>

using namespace iDynTree;

//void checkStateIsDefaultOne(DynamicsComputations & dynComp)
//{
//    dynComp.getStat

//    ASSERT_EQUAL_TRANSFORM(notRotated_H_rotated,);
//}

double random_double()
{
    return ((double)rand()-RAND_MAX/2)/((double)RAND_MAX);
}

void setRandomState(iDynTree::HighLevel::DynamicsComputations & dynComp)
{
    size_t dofs = dynComp.getNrOfDegreesOfFreedom();
    Transform    worldTbase;
    Twist        baseVel;
    ClassicalAcc baseAcc;
    SpatialAcc gravity;
    gravity.zero();
    Vector6    properAcc;

    iDynTree::VectorDynSize qj(dofs), dqj(dofs), ddqj(dofs);

    worldTbase = //iDynTree::Transform::Identity();
    iDynTree::Transform(Rotation::RPY(random_double(),random_double(),random_double()),
            Position(random_double(),random_double(),random_double()));

    for(int i=0; i < 3; i++)
    {
        gravity(i) = random_double();
    }

    gravity(2) = 10.0;

    for(int i=0; i < 6; i++)
    {
        baseVel(i) = random_double();
        baseAcc(i) = random_double();
        properAcc(i) = baseAcc(i) + gravity(i);
    }

    for(size_t dof=0; dof < dofs; dof++)

    {
        qj(dof) = random_double();
        dqj(dof) = random_double();
        ddqj(dof) = random_double();
    }

    bool ok = dynComp.setRobotState(qj,dqj,ddqj,worldTbase,baseVel,baseAcc,gravity);

    ASSERT_EQUAL_DOUBLE(ok,true);
}

void testJacobianVsForwardKinematicsConsistency(iDynTree::HighLevel::DynamicsComputations & dynComp)
{
    size_t dofs = dynComp.getNrOfDegreesOfFreedom();
    size_t frames = dynComp.getNrOfFrames();

    MatrixDynSize jac(6,6+dofs);
    Eigen::VectorXd robotVel(6+dofs);

    Vector6 velBaseTwist = dynComp.getBaseTwist().asVector();
    robotVel.segment(0,6) = toEigen(velBaseTwist);
    VectorDynSize jointVel(dofs);
    dynComp.getJointVel(jointVel);
    robotVel.segment(6,dofs) = toEigen(jointVel);

    Twist velFromJac, velFromFwdKin;

    for(size_t frame=0; frame < frames; frame++)
    {
        velFromFwdKin = dynComp.getFrameTwistInWorldOrient(frame);
        dynComp.getFrameJacobian(frame,jac);

        Eigen::Matrix<double,6,1> velJac = toEigen(jac)*robotVel;

        toEigen(velFromJac.getLinearVec3()) = velJac.segment<3>(0);
        toEigen(velFromJac.getAngularVec3()) = velJac.segment<3>(3);
    }

    ASSERT_EQUAL_VECTOR(velFromFwdKin.asVector(),velFromJac.asVector());
}

void testRegressorVsInverseDynamicsConsistency(iDynTree::HighLevel::DynamicsComputations & dynComp)
{
    size_t dofs = dynComp.getNrOfDegreesOfFreedom();
    size_t nrOfLinks = dynComp.getNrOfLinks();

    // check regressor matrix
    MatrixDynSize dynRegressor(6+dofs,10*nrOfLinks);
    dynComp.getDynamicsRegressor(dynRegressor);

    // check parameter vector
    VectorDynSize dynParams(10*nrOfLinks);
    dynComp.getModelDynamicsParameters(dynParams);

    // compute inverseDynamics with regressor
    VectorDynSize idResultRegr(6+dofs), torquesRegr(dofs), torquesID(dofs);
    Wrench baseWrenchID, baseWrenchRegr;
    toEigen(idResultRegr) = toEigen(dynRegressor)*toEigen(dynParams);

    toEigen(baseWrenchRegr.getLinearVec3()) = toEigen(idResultRegr).segment(0,3);
    toEigen(baseWrenchRegr.getAngularVec3()) = toEigen(idResultRegr).segment(3,3);

    toEigen(torquesRegr)    = toEigen(idResultRegr).segment(6,dofs);

    // compute inverseDynam
    dynComp.inverseDynamics(torquesID,baseWrenchID);

    ASSERT_EQUAL_VECTOR(torquesID,torquesRegr);
    ASSERT_EQUAL_VECTOR(baseWrenchID,baseWrenchRegr);
}

void testModelConsistency(std::string modelFilePath)
{
    HighLevel::DynamicsComputations dynComp;

    bool ok = dynComp.loadRobotModelFromFile(modelFilePath);

    setRandomState(dynComp);

    testJacobianVsForwardKinematicsConsistency(dynComp);
    testRegressorVsInverseDynamicsConsistency(dynComp);
}

void testTwoLinksRotationOnZAxisRegressor()
{
    std::string urdfFileName = getAbsModelPath("twoLinksRotationOnZAxis.urdf");
    HighLevel::DynamicsComputations dynComp;
    bool ok = dynComp.loadRobotModelFromFile(urdfFileName);
    ASSERT_IS_TRUE(ok);

    setRandomState(dynComp);

    MatrixDynSize regr;
    ok = dynComp.getDynamicsRegressor(regr);
    ASSERT_IS_TRUE(ok);
    std::cerr << regr.toString() << std::endl;
}

int main()
{
    for(unsigned int mdl = 0; mdl < IDYNTREE_TESTS_URDFS_NR; mdl++ )
    {
        std::string urdfFileName = getAbsModelPath(std::string(IDYNTREE_TESTS_URDFS[mdl]));
        std::cout << "Testing file " << std::string(IDYNTREE_TESTS_URDFS[mdl]) <<  std::endl;
        testModelConsistency(urdfFileName);
    }

    // Do a special test for the regression on a model that just has 1 joint that rotates
    // around the Z axis, and both link frames have the origin on that axes
    testTwoLinksRotationOnZAxisRegressor();

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/nest/p9_htm_adu_ctrl.H $   */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/// ----------------------------------------------------------------------------
/// @file  p9_htm_adu_ctrl.H
///
/// @brief Provides ADU control functions that help with HTM collection actions.
///
/// ----------------------------------------------------------------------------
/// *HWP HWP Owner   : Joe McGill <jmcgill@us.ibm.com>
/// *HWP FW Owner    : Thi Tran <thi@us.ibm.com>
/// *HWP Team        : Nest
/// *HWP Level       : 2
/// *HWP Consumed by : HB
/// ----------------------------------------------------------------------------

#ifndef _P9_HTM_ADU_CTRL_H_
#define _P9_HTM_ADU_CTRL_H_

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------
#include <fapi2.H>

//------------------------------------------------------------------------------
// Function prototypes
//------------------------------------------------------------------------------
///
/// @brief Use ADU to trigger start/stop globally the NHTM engines
///
/// @param[in] i_target        Reference to target
/// @param[in] i_address       Address of PMISC command that should have
///                            the start/stop/pause bits set accordingly.
///
///
/// @return FAPI2_RC_SUCCESS if success, else error code.
///
fapi2::ReturnCode aduNHTMControl(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
    const uint64_t i_addr);

#endif  // _P9_HTM_ADU_CTRL_H_
<commit_msg>L3 update -- p9_htm_setup/pause/start/stop HWPs<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/nest/p9_htm_adu_ctrl.H $   */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/// ----------------------------------------------------------------------------
/// @file  p9_htm_adu_ctrl.H
///
/// @brief Provides ADU control functions that help with HTM collection actions.
///
/// ----------------------------------------------------------------------------
/// *HWP HWP Owner   : Joe McGill <jmcgill@us.ibm.com>
/// *HWP FW Owner    : Thi Tran <thi@us.ibm.com>
/// *HWP Team        : Nest
/// *HWP Level       : 3
/// *HWP Consumed by : HB
/// ----------------------------------------------------------------------------

#ifndef _P9_HTM_ADU_CTRL_H_
#define _P9_HTM_ADU_CTRL_H_

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------
#include <fapi2.H>

//------------------------------------------------------------------------------
// Function prototypes
//------------------------------------------------------------------------------
///
/// @brief Use ADU to globally trigger start/stop NHTM engines
///
/// @param[in] i_target        Reference to target
/// @param[in] i_addr          Address of PMISC command that should have
///                            the start/stop/pause bits set accordingly.
///
///
/// @return FAPI2_RC_SUCCESS if success, else error code.
///
fapi2::ReturnCode aduNHTMControl(
    const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
    const uint64_t i_addr);

#endif  // _P9_HTM_ADU_CTRL_H_
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/renderer_host/render_process_host.h"

#include "base/rand_util.h"
#include "base/sys_info.h"
#include "chrome/browser/child_process_security_policy.h"
#include "chrome/common/child_process_info.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/notification_service.h"

namespace {

size_t GetMaxRendererProcessCount() {
  // Defines the maximum number of renderer processes according to the
  // amount of installed memory as reported by the OS. The table
  // values are calculated by assuming that you want the renderers to
  // use half of the installed ram and assuming that each tab uses
  // ~40MB, however the curve is not linear but piecewise linear with
  // interleaved slopes of 3 and 2.
  // If you modify this table you need to adjust browser\browser_uitest.cc
  // to match the expected number of processes.

  static const size_t kMaxRenderersByRamTier[] = {
    3,                        // less than 256MB
    6,                        //  256MB
    9,                        //  512MB
    12,                       //  768MB
    14,                       // 1024MB
    18,                       // 1280MB
    20,                       // 1536MB
    22,                       // 1792MB
    24,                       // 2048MB
    26,                       // 2304MB
    29,                       // 2560MB
    32,                       // 2816MB
    35,                       // 3072MB
    38,                       // 3328MB
    40                        // 3584MB
  };

  static size_t max_count = 0;
  if (!max_count) {
    size_t memory_tier = base::SysInfo::AmountOfPhysicalMemoryMB() / 256;
    if (memory_tier >= arraysize(kMaxRenderersByRamTier))
      max_count = chrome::kMaxRendererProcessCount;
    else
      max_count = kMaxRenderersByRamTier[memory_tier];
  }
  return max_count;
}

// Returns true if the given host is suitable for launching a new view
// associated with the given profile.
static bool IsSuitableHost(RenderProcessHost* host, Profile* profile,
                           RenderProcessHost::Type type) {
  if (host->profile() != profile)
    return false;

  RenderProcessHost::Type host_type = RenderProcessHost::TYPE_NORMAL;
  if (ChildProcessSecurityPolicy::GetInstance()->HasDOMUIBindings(host->id()))
    host_type = RenderProcessHost::TYPE_DOMUI;
  if (ChildProcessSecurityPolicy::GetInstance()->
        HasExtensionBindings(host->id()))
    host_type = RenderProcessHost::TYPE_EXTENSION;

  return host_type == type;
}

// the global list of all renderer processes
IDMap<RenderProcessHost> all_hosts;

}  // namespace

bool RenderProcessHost::run_renderer_in_process_ = false;

RenderProcessHost::RenderProcessHost(Profile* profile)
    : max_page_id_(-1),
      fast_shutdown_started_(false),
      id_(ChildProcessInfo::GenerateChildProcessUniqueId()),
      profile_(profile),
      sudden_termination_allowed_(true),
      ignore_input_events_(false) {
  all_hosts.AddWithID(this, id());
  all_hosts.set_check_on_null_data(true);
}

RenderProcessHost::~RenderProcessHost() {
  all_hosts.Remove(id());
}

void RenderProcessHost::Attach(IPC::Channel::Listener* listener,
                               int routing_id) {
  listeners_.AddWithID(listener, routing_id);
}

void RenderProcessHost::Release(int listener_id) {
  DCHECK(listeners_.Lookup(listener_id) != NULL);
  listeners_.Remove(listener_id);

  // Make sure that all associated resource requests are stopped.
  CancelResourceRequests(listener_id);

  // When no other owners of this object, we can delete ourselves
  if (listeners_.IsEmpty()) {
    NotificationService::current()->Notify(
        NotificationType::RENDERER_PROCESS_TERMINATED,
        Source<RenderProcessHost>(this), NotificationService::NoDetails());
    MessageLoop::current()->DeleteSoon(FROM_HERE, this);
  }
}

void RenderProcessHost::ReportExpectingClose(int32 listener_id) {
  listeners_expecting_close_.insert(listener_id);
}

void RenderProcessHost::UpdateMaxPageID(int32 page_id) {
  if (page_id > max_page_id_)
    max_page_id_ = page_id;
}

bool RenderProcessHost::FastShutdownForPageCount(size_t count) {
  if (listeners_.size() == count)
    return FastShutdownIfPossible();
  return false;
}

// static
RenderProcessHost::iterator RenderProcessHost::AllHostsIterator() {
  return iterator(&all_hosts);
}

// static
RenderProcessHost* RenderProcessHost::FromID(int render_process_id) {
  return all_hosts.Lookup(render_process_id);
}

// static
bool RenderProcessHost::ShouldTryToUseExistingProcessHost() {
  size_t renderer_process_count = all_hosts.size();

  // NOTE: Sometimes it's necessary to create more render processes than
  //       GetMaxRendererProcessCount(), for instance when we want to create
  //       a renderer process for a profile that has no existing renderers.
  //       This is OK in moderation, since the GetMaxRendererProcessCount()
  //       is conservative.

  return run_renderer_in_process() ||
         (renderer_process_count >= GetMaxRendererProcessCount());
}

// static
RenderProcessHost* RenderProcessHost::GetExistingProcessHost(Profile* profile,
                                                             Type type) {
  // First figure out which existing renderers we can use.
  std::vector<RenderProcessHost*> suitable_renderers;
  suitable_renderers.reserve(all_hosts.size());

  iterator iter(AllHostsIterator());
  while (!iter.IsAtEnd()) {
    if (run_renderer_in_process() ||
        IsSuitableHost(iter.GetCurrentValue(), profile, type))
      suitable_renderers.push_back(iter.GetCurrentValue());

    iter.Advance();
  }

  // Now pick a random suitable renderer, if we have any.
  if (!suitable_renderers.empty()) {
    int suitable_count = static_cast<int>(suitable_renderers.size());
    int random_index = base::RandInt(0, suitable_count - 1);
    return suitable_renderers[random_index];
  }

  return NULL;
}
<commit_msg>Remove the RenderProcessHost from the list of renderer processes when we call DeleteSoon, not in the destructor.  Otherewise the process can be reused in the meantime.  This matches what we do in ChildProcessHost.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/renderer_host/render_process_host.h"

#include "base/rand_util.h"
#include "base/sys_info.h"
#include "chrome/browser/child_process_security_policy.h"
#include "chrome/common/child_process_info.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/notification_service.h"

namespace {

size_t GetMaxRendererProcessCount() {
  // Defines the maximum number of renderer processes according to the
  // amount of installed memory as reported by the OS. The table
  // values are calculated by assuming that you want the renderers to
  // use half of the installed ram and assuming that each tab uses
  // ~40MB, however the curve is not linear but piecewise linear with
  // interleaved slopes of 3 and 2.
  // If you modify this table you need to adjust browser\browser_uitest.cc
  // to match the expected number of processes.

  static const size_t kMaxRenderersByRamTier[] = {
    3,                        // less than 256MB
    6,                        //  256MB
    9,                        //  512MB
    12,                       //  768MB
    14,                       // 1024MB
    18,                       // 1280MB
    20,                       // 1536MB
    22,                       // 1792MB
    24,                       // 2048MB
    26,                       // 2304MB
    29,                       // 2560MB
    32,                       // 2816MB
    35,                       // 3072MB
    38,                       // 3328MB
    40                        // 3584MB
  };

  static size_t max_count = 0;
  if (!max_count) {
    size_t memory_tier = base::SysInfo::AmountOfPhysicalMemoryMB() / 256;
    if (memory_tier >= arraysize(kMaxRenderersByRamTier))
      max_count = chrome::kMaxRendererProcessCount;
    else
      max_count = kMaxRenderersByRamTier[memory_tier];
  }
  return max_count;
}

// Returns true if the given host is suitable for launching a new view
// associated with the given profile.
static bool IsSuitableHost(RenderProcessHost* host, Profile* profile,
                           RenderProcessHost::Type type) {
  if (host->profile() != profile)
    return false;

  RenderProcessHost::Type host_type = RenderProcessHost::TYPE_NORMAL;
  if (ChildProcessSecurityPolicy::GetInstance()->HasDOMUIBindings(host->id()))
    host_type = RenderProcessHost::TYPE_DOMUI;
  if (ChildProcessSecurityPolicy::GetInstance()->
        HasExtensionBindings(host->id()))
    host_type = RenderProcessHost::TYPE_EXTENSION;

  return host_type == type;
}

// the global list of all renderer processes
IDMap<RenderProcessHost> all_hosts;

}  // namespace

bool RenderProcessHost::run_renderer_in_process_ = false;

RenderProcessHost::RenderProcessHost(Profile* profile)
    : max_page_id_(-1),
      fast_shutdown_started_(false),
      id_(ChildProcessInfo::GenerateChildProcessUniqueId()),
      profile_(profile),
      sudden_termination_allowed_(true),
      ignore_input_events_(false) {
  all_hosts.AddWithID(this, id());
  all_hosts.set_check_on_null_data(true);
}

RenderProcessHost::~RenderProcessHost() {
  // In unit tests, Release() might not have been called.
  if (all_hosts.Lookup(id()))
    all_hosts.Remove(id());
}

void RenderProcessHost::Attach(IPC::Channel::Listener* listener,
                               int routing_id) {
  listeners_.AddWithID(listener, routing_id);
}

void RenderProcessHost::Release(int listener_id) {
  DCHECK(listeners_.Lookup(listener_id) != NULL);
  listeners_.Remove(listener_id);

  // Make sure that all associated resource requests are stopped.
  CancelResourceRequests(listener_id);

  // When no other owners of this object, we can delete ourselves
  if (listeners_.IsEmpty()) {
    NotificationService::current()->Notify(
        NotificationType::RENDERER_PROCESS_TERMINATED,
        Source<RenderProcessHost>(this), NotificationService::NoDetails());
    MessageLoop::current()->DeleteSoon(FROM_HERE, this);

    // Remove ourself from the list of renderer processes so that we can't be
    // reused in between now and when the Delete task runs.
    all_hosts.Remove(id());
  }
}

void RenderProcessHost::ReportExpectingClose(int32 listener_id) {
  listeners_expecting_close_.insert(listener_id);
}

void RenderProcessHost::UpdateMaxPageID(int32 page_id) {
  if (page_id > max_page_id_)
    max_page_id_ = page_id;
}

bool RenderProcessHost::FastShutdownForPageCount(size_t count) {
  if (listeners_.size() == count)
    return FastShutdownIfPossible();
  return false;
}

// static
RenderProcessHost::iterator RenderProcessHost::AllHostsIterator() {
  return iterator(&all_hosts);
}

// static
RenderProcessHost* RenderProcessHost::FromID(int render_process_id) {
  return all_hosts.Lookup(render_process_id);
}

// static
bool RenderProcessHost::ShouldTryToUseExistingProcessHost() {
  size_t renderer_process_count = all_hosts.size();

  // NOTE: Sometimes it's necessary to create more render processes than
  //       GetMaxRendererProcessCount(), for instance when we want to create
  //       a renderer process for a profile that has no existing renderers.
  //       This is OK in moderation, since the GetMaxRendererProcessCount()
  //       is conservative.

  return run_renderer_in_process() ||
         (renderer_process_count >= GetMaxRendererProcessCount());
}

// static
RenderProcessHost* RenderProcessHost::GetExistingProcessHost(Profile* profile,
                                                             Type type) {
  // First figure out which existing renderers we can use.
  std::vector<RenderProcessHost*> suitable_renderers;
  suitable_renderers.reserve(all_hosts.size());

  iterator iter(AllHostsIterator());
  while (!iter.IsAtEnd()) {
    if (run_renderer_in_process() ||
        IsSuitableHost(iter.GetCurrentValue(), profile, type))
      suitable_renderers.push_back(iter.GetCurrentValue());

    iter.Advance();
  }

  // Now pick a random suitable renderer, if we have any.
  if (!suitable_renderers.empty()) {
    int suitable_count = static_cast<int>(suitable_renderers.size());
    int random_index = base::RandInt(0, suitable_count - 1);
    return suitable_renderers[random_index];
  }

  return NULL;
}
<|endoftext|>


<commit_before>/** Copyright (C) 2018 European Spallation Source ERIC */

/** @file
 *
 *  \brief Unit tests.
 */

#include "../AdcReadoutBase.h"
#include "TestUDPServer.h"
#include <gtest/gtest.h>
#include <trompeloeil.hpp>

class AdcReadoutStandIn : public AdcReadoutBase {
public:
  AdcReadoutStandIn(BaseSettings Settings, AdcSettings ReadoutSettings)
      : AdcReadoutBase(Settings, ReadoutSettings){};
  ~AdcReadoutStandIn() = default;
  using Detector::Threads;
  using AdcReadoutBase::AdcStats;
  using AdcReadoutBase::DataModuleQueues;
  static const int MaxPacketSize = 2048;
  std::uint8_t BufferPtr[MaxPacketSize];
  int PacketSize;
  void LoadPacketFile(std::string FileName) {
    std::string PacketPath = TEST_PACKET_PATH;
    std::ifstream PacketFile(PacketPath + FileName, std::ios::binary);
    ASSERT_TRUE(PacketFile.good());
    PacketFile.seekg(0, std::ios::end);
    PacketSize = PacketFile.tellg();
    PacketFile.seekg(0, std::ios::beg);
    PacketFile.read(reinterpret_cast<char *>(&BufferPtr), PacketSize);
    ASSERT_TRUE(PacketFile.good());
  }
};

using namespace std::chrono_literals;

class AdcReadoutTest : public ::testing::Test {
public:
  virtual void SetUp() {
    Settings.DetectorAddress = "0.0.0.0";
    Settings.DetectorPort = GetPortNumber();
    ReadoutSettings.AltDetectorInterface = "0.0.0.0";
    ReadoutSettings.AltDetectorPort = GetPortNumber();
  }
  BaseSettings Settings;
  AdcSettings ReadoutSettings;

  static const int MaxPacketSize = 10000;
  std::uint8_t BufferPtr[MaxPacketSize];
  int PacketSize;

  void LoadPacketFile(std::string FileName) {
    std::string PacketPath = TEST_PACKET_PATH;
    std::ifstream PacketFile(PacketPath + FileName, std::ios::binary);
    ASSERT_TRUE(PacketFile.good());
    PacketFile.seekg(0, std::ios::end);
    PacketSize = PacketFile.tellg();
    PacketFile.seekg(0, std::ios::beg);
    PacketFile.read(reinterpret_cast<char *>(&BufferPtr), PacketSize);
    ASSERT_TRUE(PacketFile.good());
  };
  std::chrono::duration<std::int64_t, std::milli> SleepTime{50ms};
};

TEST_F(AdcReadoutTest, SinglePacketStats) {
  AdcReadoutStandIn Readout(Settings, ReadoutSettings);
  Readout.startThreads();
  TestUDPServer Server(GetPortNumber(), Settings.DetectorPort, 1470);
  std::this_thread::sleep_for(SleepTime);
  Server.startPacketTransmission(1, 100);
  std::this_thread::sleep_for(SleepTime);
  Readout.stopThreads();
  EXPECT_EQ(Readout.AdcStats.input_bytes_received, 1470);
  EXPECT_EQ(Readout.AdcStats.parser_errors, 1);
}

TEST_F(AdcReadoutTest, SingleIdlePacket) {
  AdcReadoutStandIn Readout(Settings, ReadoutSettings);
  Readout.startThreads();
  LoadPacketFile("test_packet_idle.dat");
  TestUDPServer Server(GetPortNumber(), Settings.DetectorPort, BufferPtr,
                       PacketSize);
  std::this_thread::sleep_for(SleepTime);
  Server.startPacketTransmission(1, 100);
  std::this_thread::sleep_for(SleepTime);
  Readout.stopThreads();
  EXPECT_EQ(Readout.AdcStats.input_bytes_received, 22);
  EXPECT_EQ(Readout.AdcStats.parser_packets_total, 1);
  EXPECT_EQ(Readout.AdcStats.parser_packets_idle, 1);
  EXPECT_EQ(Readout.AdcStats.processing_packets_lost, 0);
}

TEST_F(AdcReadoutTest, SingleDataPacket) {
  try {
    AdcReadoutStandIn Readout(Settings, ReadoutSettings);
    Readout.startThreads();
    LoadPacketFile("test_packet_1.dat");
    TestUDPServer Server(GetPortNumber(), Settings.DetectorPort, BufferPtr,
                         PacketSize);
    std::this_thread::sleep_for(20ms);
    Server.startPacketTransmission(1, 100);
    std::this_thread::sleep_for(20ms);
    Readout.stopThreads();
    EXPECT_EQ(Readout.AdcStats.input_bytes_received, 1470);
    EXPECT_EQ(Readout.AdcStats.parser_packets_total, 1);
    EXPECT_EQ(Readout.AdcStats.parser_packets_data, 1);
    EXPECT_EQ(Readout.AdcStats.processing_packets_lost, 0);
  } catch (std::out_of_range &E) {
    std::cout << "SingleDataPacket(): Got exception, what: " << E.what() << std::endl;
    throw E;
  }
}

TEST_F(AdcReadoutTest, LazyThreadLaunching) {
  AdcReadoutStandIn Readout(Settings, ReadoutSettings);
  Readout.startThreads();
  EXPECT_EQ(Readout.Threads.size(), 1u);
  LoadPacketFile("test_packet_1.dat");
  TestUDPServer Server(GetPortNumber(), Settings.DetectorPort, BufferPtr,
                       PacketSize);
  std::this_thread::sleep_for(SleepTime);
  Server.startPacketTransmission(1, 100);
  std::this_thread::sleep_for(SleepTime);
  EXPECT_EQ(Readout.Threads.size(), 2u);
  Readout.stopThreads();
}

TEST_F(AdcReadoutTest, DoubleReceiveTest) {
  AdcReadoutStandIn Readout(Settings, ReadoutSettings);
  Readout.startThreads();
  LoadPacketFile("test_packet_1.dat");
  TestUDPServer Server1(GetPortNumber(), Settings.DetectorPort, BufferPtr,
                        PacketSize);
  TestUDPServer Server2(GetPortNumber(), ReadoutSettings.AltDetectorPort,
                        BufferPtr, PacketSize);
  std::this_thread::sleep_for(SleepTime);
  Server1.startPacketTransmission(1, 100);
  Server2.startPacketTransmission(1, 100);
  std::this_thread::sleep_for(SleepTime);
  EXPECT_EQ(Readout.Threads.size(), 3u);
  EXPECT_EQ(Readout.AdcStats.parser_packets_total, 2);
  Readout.stopThreads();
}

TEST_F(AdcReadoutTest, GlobalCounterError) {
  AdcReadoutStandIn Readout(Settings, ReadoutSettings);
  Readout.startThreads();
  LoadPacketFile("test_packet_1.dat");
  TestUDPServer Server(GetPortNumber(), Settings.DetectorPort, BufferPtr,
                       PacketSize);
  std::this_thread::sleep_for(SleepTime);
  Server.startPacketTransmission(2, 100);
  std::this_thread::sleep_for(SleepTime);
  Readout.stopThreads();
  EXPECT_EQ(Readout.AdcStats.input_bytes_received, 2 * 1470);
  EXPECT_EQ(Readout.AdcStats.parser_packets_total, 2);
  EXPECT_EQ(Readout.AdcStats.parser_errors, 0);
  EXPECT_EQ(Readout.AdcStats.parser_packets_data, 2);
  EXPECT_EQ(Readout.AdcStats.processing_packets_lost, 1);
}

TEST_F(AdcReadoutTest, GlobalCounterCorrect) {
  AdcReadoutStandIn Readout(Settings, ReadoutSettings);
  Readout.startThreads();
  LoadPacketFile("test_packet_1.dat");
  std::this_thread::sleep_for(SleepTime);
  auto PacketHeadPointer = reinterpret_cast<PacketHeader *>(BufferPtr);
  {
    TestUDPServer Server1(GetPortNumber(), Settings.DetectorPort, BufferPtr,
                          PacketSize);
    Server1.startPacketTransmission(1, 100);
    std::this_thread::sleep_for(SleepTime);
  }
  PacketHeadPointer->fixEndian();
  PacketHeadPointer->GlobalCount++;
  PacketHeadPointer->fixEndian();
  {
    TestUDPServer Server2(GetPortNumber(), Settings.DetectorPort, BufferPtr,
                          PacketSize);
    Server2.startPacketTransmission(1, 100);
    std::this_thread::sleep_for(SleepTime);
  }
  Readout.stopThreads();
  EXPECT_EQ(Readout.AdcStats.input_bytes_received, 2 * 1470);
  EXPECT_EQ(Readout.AdcStats.parser_packets_total, 2);
  EXPECT_EQ(Readout.AdcStats.parser_errors, 0);
  EXPECT_EQ(Readout.AdcStats.parser_packets_data, 2);
  EXPECT_EQ(Readout.AdcStats.processing_packets_lost, 0);
}

using trompeloeil::_;

class AdcReadoutMock : public AdcReadoutBase {
public:
  AdcReadoutMock(BaseSettings Settings, AdcSettings ReadoutSettings)
      : AdcReadoutBase(Settings, ReadoutSettings){};
  using Detector::Threads;
  using AdcReadoutBase::DataModuleQueues;
  MAKE_MOCK0(inputThread, void(), override);
  MAKE_MOCK1(processingThread, void(Queue &), override);
};

class AdcReadoutSimpleTest : public ::testing::Test {
public:
  BaseSettings Settings;
  AdcSettings ReadoutSettings;
};

TEST_F(AdcReadoutSimpleTest, StartProcessingThreads) {
  AdcReadoutMock Readout(Settings, ReadoutSettings);
  REQUIRE_CALL(Readout, inputThread()).TIMES(1);
  REQUIRE_CALL(Readout, processingThread(_)).TIMES(0);
  Readout.startThreads();
  Readout.stopThreads();
}

TEST_F(AdcReadoutSimpleTest, DataQueues) {
  AdcReadoutMock Readout(Settings, ReadoutSettings);
  EXPECT_EQ(Readout.DataModuleQueues.size(), 0u);
}
<commit_msg>Disabled test.<commit_after>/** Copyright (C) 2018 European Spallation Source ERIC */

/** @file
 *
 *  \brief Unit tests.
 */

#include "../AdcReadoutBase.h"
#include "TestUDPServer.h"
#include <gtest/gtest.h>
#include <trompeloeil.hpp>

class AdcReadoutStandIn : public AdcReadoutBase {
public:
  AdcReadoutStandIn(BaseSettings Settings, AdcSettings ReadoutSettings)
      : AdcReadoutBase(Settings, ReadoutSettings){};
  ~AdcReadoutStandIn() = default;
  using Detector::Threads;
  using AdcReadoutBase::AdcStats;
  using AdcReadoutBase::DataModuleQueues;
  static const int MaxPacketSize = 2048;
  std::uint8_t BufferPtr[MaxPacketSize];
  int PacketSize;
  void LoadPacketFile(std::string FileName) {
    std::string PacketPath = TEST_PACKET_PATH;
    std::ifstream PacketFile(PacketPath + FileName, std::ios::binary);
    ASSERT_TRUE(PacketFile.good());
    PacketFile.seekg(0, std::ios::end);
    PacketSize = PacketFile.tellg();
    PacketFile.seekg(0, std::ios::beg);
    PacketFile.read(reinterpret_cast<char *>(&BufferPtr), PacketSize);
    ASSERT_TRUE(PacketFile.good());
  }
};

using namespace std::chrono_literals;

class AdcReadoutTest : public ::testing::Test {
public:
  virtual void SetUp() {
    Settings.DetectorAddress = "0.0.0.0";
    Settings.DetectorPort = GetPortNumber();
    ReadoutSettings.AltDetectorInterface = "0.0.0.0";
    ReadoutSettings.AltDetectorPort = GetPortNumber();
  }
  BaseSettings Settings;
  AdcSettings ReadoutSettings;

  static const int MaxPacketSize = 10000;
  std::uint8_t BufferPtr[MaxPacketSize];
  int PacketSize;

  void LoadPacketFile(std::string FileName) {
    std::string PacketPath = TEST_PACKET_PATH;
    std::ifstream PacketFile(PacketPath + FileName, std::ios::binary);
    ASSERT_TRUE(PacketFile.good());
    PacketFile.seekg(0, std::ios::end);
    PacketSize = PacketFile.tellg();
    PacketFile.seekg(0, std::ios::beg);
    PacketFile.read(reinterpret_cast<char *>(&BufferPtr), PacketSize);
    ASSERT_TRUE(PacketFile.good());
  };
  std::chrono::duration<std::int64_t, std::milli> SleepTime{50ms};
};

TEST_F(AdcReadoutTest, SinglePacketStats) {
  AdcReadoutStandIn Readout(Settings, ReadoutSettings);
  Readout.startThreads();
  TestUDPServer Server(GetPortNumber(), Settings.DetectorPort, 1470);
  std::this_thread::sleep_for(SleepTime);
  Server.startPacketTransmission(1, 100);
  std::this_thread::sleep_for(SleepTime);
  Readout.stopThreads();
  EXPECT_EQ(Readout.AdcStats.input_bytes_received, 1470);
  EXPECT_EQ(Readout.AdcStats.parser_errors, 1);
}

TEST_F(AdcReadoutTest, SingleIdlePacket) {
  AdcReadoutStandIn Readout(Settings, ReadoutSettings);
  Readout.startThreads();
  LoadPacketFile("test_packet_idle.dat");
  TestUDPServer Server(GetPortNumber(), Settings.DetectorPort, BufferPtr,
                       PacketSize);
  std::this_thread::sleep_for(SleepTime);
  Server.startPacketTransmission(1, 100);
  std::this_thread::sleep_for(SleepTime);
  Readout.stopThreads();
  EXPECT_EQ(Readout.AdcStats.input_bytes_received, 22);
  EXPECT_EQ(Readout.AdcStats.parser_packets_total, 1);
  EXPECT_EQ(Readout.AdcStats.parser_packets_idle, 1);
  EXPECT_EQ(Readout.AdcStats.processing_packets_lost, 0);
}

TEST_F(AdcReadoutTest, DISABLED_SingleDataPacket) {
  try {
    AdcReadoutStandIn Readout(Settings, ReadoutSettings);
    Readout.startThreads();
    LoadPacketFile("test_packet_1.dat");
    TestUDPServer Server(GetPortNumber(), Settings.DetectorPort, BufferPtr,
                         PacketSize);
    std::this_thread::sleep_for(20ms);
    Server.startPacketTransmission(1, 100);
    std::this_thread::sleep_for(20ms);
    Readout.stopThreads();
    EXPECT_EQ(Readout.AdcStats.input_bytes_received, 1470);
    EXPECT_EQ(Readout.AdcStats.parser_packets_total, 1);
    EXPECT_EQ(Readout.AdcStats.parser_packets_data, 1);
    EXPECT_EQ(Readout.AdcStats.processing_packets_lost, 0);
  } catch (std::out_of_range &E) {
    std::cout << "SingleDataPacket(): Got exception, what: " << E.what() << std::endl;
    throw E;
  }
}

TEST_F(AdcReadoutTest, LazyThreadLaunching) {
  AdcReadoutStandIn Readout(Settings, ReadoutSettings);
  Readout.startThreads();
  EXPECT_EQ(Readout.Threads.size(), 1u);
  LoadPacketFile("test_packet_1.dat");
  TestUDPServer Server(GetPortNumber(), Settings.DetectorPort, BufferPtr,
                       PacketSize);
  std::this_thread::sleep_for(SleepTime);
  Server.startPacketTransmission(1, 100);
  std::this_thread::sleep_for(SleepTime);
  EXPECT_EQ(Readout.Threads.size(), 2u);
  Readout.stopThreads();
}

TEST_F(AdcReadoutTest, DoubleReceiveTest) {
  AdcReadoutStandIn Readout(Settings, ReadoutSettings);
  Readout.startThreads();
  LoadPacketFile("test_packet_1.dat");
  TestUDPServer Server1(GetPortNumber(), Settings.DetectorPort, BufferPtr,
                        PacketSize);
  TestUDPServer Server2(GetPortNumber(), ReadoutSettings.AltDetectorPort,
                        BufferPtr, PacketSize);
  std::this_thread::sleep_for(SleepTime);
  Server1.startPacketTransmission(1, 100);
  Server2.startPacketTransmission(1, 100);
  std::this_thread::sleep_for(SleepTime);
  EXPECT_EQ(Readout.Threads.size(), 3u);
  EXPECT_EQ(Readout.AdcStats.parser_packets_total, 2);
  Readout.stopThreads();
}

TEST_F(AdcReadoutTest, GlobalCounterError) {
  AdcReadoutStandIn Readout(Settings, ReadoutSettings);
  Readout.startThreads();
  LoadPacketFile("test_packet_1.dat");
  TestUDPServer Server(GetPortNumber(), Settings.DetectorPort, BufferPtr,
                       PacketSize);
  std::this_thread::sleep_for(SleepTime);
  Server.startPacketTransmission(2, 100);
  std::this_thread::sleep_for(SleepTime);
  Readout.stopThreads();
  EXPECT_EQ(Readout.AdcStats.input_bytes_received, 2 * 1470);
  EXPECT_EQ(Readout.AdcStats.parser_packets_total, 2);
  EXPECT_EQ(Readout.AdcStats.parser_errors, 0);
  EXPECT_EQ(Readout.AdcStats.parser_packets_data, 2);
  EXPECT_EQ(Readout.AdcStats.processing_packets_lost, 1);
}

TEST_F(AdcReadoutTest, GlobalCounterCorrect) {
  AdcReadoutStandIn Readout(Settings, ReadoutSettings);
  Readout.startThreads();
  LoadPacketFile("test_packet_1.dat");
  std::this_thread::sleep_for(SleepTime);
  auto PacketHeadPointer = reinterpret_cast<PacketHeader *>(BufferPtr);
  {
    TestUDPServer Server1(GetPortNumber(), Settings.DetectorPort, BufferPtr,
                          PacketSize);
    Server1.startPacketTransmission(1, 100);
    std::this_thread::sleep_for(SleepTime);
  }
  PacketHeadPointer->fixEndian();
  PacketHeadPointer->GlobalCount++;
  PacketHeadPointer->fixEndian();
  {
    TestUDPServer Server2(GetPortNumber(), Settings.DetectorPort, BufferPtr,
                          PacketSize);
    Server2.startPacketTransmission(1, 100);
    std::this_thread::sleep_for(SleepTime);
  }
  Readout.stopThreads();
  EXPECT_EQ(Readout.AdcStats.input_bytes_received, 2 * 1470);
  EXPECT_EQ(Readout.AdcStats.parser_packets_total, 2);
  EXPECT_EQ(Readout.AdcStats.parser_errors, 0);
  EXPECT_EQ(Readout.AdcStats.parser_packets_data, 2);
  EXPECT_EQ(Readout.AdcStats.processing_packets_lost, 0);
}

using trompeloeil::_;

class AdcReadoutMock : public AdcReadoutBase {
public:
  AdcReadoutMock(BaseSettings Settings, AdcSettings ReadoutSettings)
      : AdcReadoutBase(Settings, ReadoutSettings){};
  using Detector::Threads;
  using AdcReadoutBase::DataModuleQueues;
  MAKE_MOCK0(inputThread, void(), override);
  MAKE_MOCK1(processingThread, void(Queue &), override);
};

class AdcReadoutSimpleTest : public ::testing::Test {
public:
  BaseSettings Settings;
  AdcSettings ReadoutSettings;
};

TEST_F(AdcReadoutSimpleTest, StartProcessingThreads) {
  AdcReadoutMock Readout(Settings, ReadoutSettings);
  REQUIRE_CALL(Readout, inputThread()).TIMES(1);
  REQUIRE_CALL(Readout, processingThread(_)).TIMES(0);
  Readout.startThreads();
  Readout.stopThreads();
}

TEST_F(AdcReadoutSimpleTest, DataQueues) {
  AdcReadoutMock Readout(Settings, ReadoutSettings);
  EXPECT_EQ(Readout.DataModuleQueues.size(), 0u);
}
<|endoftext|>


<commit_before>/***************************************************************************
                          constraintactivitytagpreferredroomsform.cpp  -  description
                             -------------------
    begin                : 2009
    copyright            : (C) 2009 by Lalescu Liviu
    email                : Please see http://lalescu.ro/liviu/ for details about contacting Liviu Lalescu (in particular, you can find here the e-mail address)
 ***************************************************************************/

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

#include "constraintactivitytagpreferredroomsform.h"
#include "addconstraintactivitytagpreferredroomsform.h"
#include "modifyconstraintactivitytagpreferredroomsform.h"

#include "teacherstudentsetsubjectactivitytag_filterwidget.h"

ConstraintActivityTagPreferredRoomsForm::ConstraintActivityTagPreferredRoomsForm(QWidget* parent): SpaceConstraintBaseDialog(parent)
{
	const char *context = "ConstraintActivityTagPreferredRoomsForm_template";
	//: This is the title of the dialog to see the list of all constraints of this type
	setWindowTitle(QCoreApplication::translate(context, "Constraints activity tag preferred rooms"));

	TeacherStudentSetSubjectActivityTag_FilterWidget *filterWidget = new TeacherStudentSetSubjectActivityTag_FilterWidget(gt.rules);
	filterWidget->setActivityTagsVisible(true);
	setFilterWidget(filterWidget);
	connect(filterWidget, &TeacherStudentSetSubjectActivityTag_FilterWidget::FilterChanged, this, &ConstraintActivityTagPreferredRoomsForm::filterChanged);

	restoreFETDialogGeometry(this);
	this->filterChanged();
}

ConstraintActivityTagPreferredRoomsForm::~ConstraintActivityTagPreferredRoomsForm()
{
	saveFETDialogGeometry(this);
}

bool ConstraintActivityTagPreferredRoomsForm::filterOk(const SpaceConstraint* ctr) const
{
	if(ctr->type==CONSTRAINT_ACTIVITY_TAG_PREFERRED_ROOMS){
		ConstraintActivityTagPreferredRooms* c=(ConstraintActivityTagPreferredRooms*)ctr;
		const TeacherStudentSetSubjectActivityTag_FilterWidget * filterWidget = static_cast<TeacherStudentSetSubjectActivityTag_FilterWidget*>(getFilterWidget());
		QString activityTag=filterWidget->activityTag();
		QString room=filterWidget->room();
		return (c->activityTagName==activityTag || activityTag=="");
	}
	else
		return false;
}

QDialog * ConstraintActivityTagPreferredRoomsForm::createAddDialog()
{
	return new AddConstraintActivityTagPreferredRoomsForm(this);
}

QDialog * ConstraintActivityTagPreferredRoomsForm::createModifyDialog(SpaceConstraint *ctr)
{
	return new ModifyConstraintActivityTagPreferredRoomsForm(this, (ConstraintActivityTagPreferredRooms*)ctr);
}
<commit_msg>code cleanup: remove useless variable<commit_after>/***************************************************************************
                          constraintactivitytagpreferredroomsform.cpp  -  description
                             -------------------
    begin                : 2009
    copyright            : (C) 2009 by Lalescu Liviu
    email                : Please see http://lalescu.ro/liviu/ for details about contacting Liviu Lalescu (in particular, you can find here the e-mail address)
 ***************************************************************************/

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

#include "constraintactivitytagpreferredroomsform.h"
#include "addconstraintactivitytagpreferredroomsform.h"
#include "modifyconstraintactivitytagpreferredroomsform.h"

#include "teacherstudentsetsubjectactivitytag_filterwidget.h"

ConstraintActivityTagPreferredRoomsForm::ConstraintActivityTagPreferredRoomsForm(QWidget* parent): SpaceConstraintBaseDialog(parent)
{
	const char *context = "ConstraintActivityTagPreferredRoomsForm_template";
	//: This is the title of the dialog to see the list of all constraints of this type
	setWindowTitle(QCoreApplication::translate(context, "Constraints activity tag preferred rooms"));

	TeacherStudentSetSubjectActivityTag_FilterWidget *filterWidget = new TeacherStudentSetSubjectActivityTag_FilterWidget(gt.rules);
	filterWidget->setActivityTagsVisible(true);
	setFilterWidget(filterWidget);
	connect(filterWidget, &TeacherStudentSetSubjectActivityTag_FilterWidget::FilterChanged, this, &ConstraintActivityTagPreferredRoomsForm::filterChanged);

	restoreFETDialogGeometry(this);
	this->filterChanged();
}

ConstraintActivityTagPreferredRoomsForm::~ConstraintActivityTagPreferredRoomsForm()
{
	saveFETDialogGeometry(this);
}

bool ConstraintActivityTagPreferredRoomsForm::filterOk(const SpaceConstraint* ctr) const
{
	if(ctr->type==CONSTRAINT_ACTIVITY_TAG_PREFERRED_ROOMS){
		ConstraintActivityTagPreferredRooms* c=(ConstraintActivityTagPreferredRooms*)ctr;
		const TeacherStudentSetSubjectActivityTag_FilterWidget * filterWidget = static_cast<TeacherStudentSetSubjectActivityTag_FilterWidget*>(getFilterWidget());
		QString activityTag=filterWidget->activityTag();
		return (c->activityTagName==activityTag || activityTag=="");
	}
	else
		return false;
}

QDialog * ConstraintActivityTagPreferredRoomsForm::createAddDialog()
{
	return new AddConstraintActivityTagPreferredRoomsForm(this);
}

QDialog * ConstraintActivityTagPreferredRoomsForm::createModifyDialog(SpaceConstraint *ctr)
{
	return new ModifyConstraintActivityTagPreferredRoomsForm(this, (ConstraintActivityTagPreferredRooms*)ctr);
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2016 ArangoDB GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
////////////////////////////////////////////////////////////////////////////////

#include "RestEngine.h"

#include <iostream>
#include "GeneralServer/RestHandler.h"
#include "Logger/Logger.h"

using namespace arangodb;
using namespace arangodb::rest;

// -----------------------------------------------------------------------------
// --SECTION--                                                    public methods
// -----------------------------------------------------------------------------

int RestEngine::asyncRun(std::shared_ptr<rest::RestHandler> handler) {
  return run(handler, false);
}

int RestEngine::syncRun(std::shared_ptr<rest::RestHandler> handler) {
  _agent = nullptr;

  _loop._ioService = nullptr;
  _loop._scheduler = nullptr;

  return run(handler, true);
}

void RestEngine::appendRestStatus(std::shared_ptr<RestStatusElement> element) {
  while (element.get() != nullptr) {
    _elements.emplace_back(element);
    element = element->previous();
  }
}

// -----------------------------------------------------------------------------
// --SECTION--                                                   private methods
// -----------------------------------------------------------------------------

int RestEngine::run(std::shared_ptr<rest::RestHandler> handler, bool synchron) {
  while (true) {
    int res = TRI_ERROR_NO_ERROR;

    switch (_state) {
      case State::PREPARE:
        res = handler->prepareEngine();
        break;

      case State::EXECUTE:
        res = handler->executeEngine();
        break;

      case State::RUN:
        res = handler->runEngine(synchron);
        break;

      case State::WAITING:
        return synchron ? TRI_ERROR_INTERNAL : TRI_ERROR_NO_ERROR;

      case State::FINALIZE:
        res = handler->finalizeEngine();
        break;

      case State::DONE:
      case State::FAILED:
        return res;
    }

    if (res != TRI_ERROR_NO_ERROR) {
      return res;
    }
  }
}
<commit_msg>Run finalizeExecute in case of errors when prepareExecute was successful.<commit_after>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2016 ArangoDB GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
////////////////////////////////////////////////////////////////////////////////

#include "RestEngine.h"

#include <iostream>
#include "GeneralServer/RestHandler.h"
#include "Logger/Logger.h"

using namespace arangodb;
using namespace arangodb::rest;

// -----------------------------------------------------------------------------
// --SECTION--                                                    public methods
// -----------------------------------------------------------------------------

int RestEngine::asyncRun(std::shared_ptr<rest::RestHandler> handler) {
  return run(handler, false);
}

int RestEngine::syncRun(std::shared_ptr<rest::RestHandler> handler) {
  _agent = nullptr;

  _loop._ioService = nullptr;
  _loop._scheduler = nullptr;

  return run(handler, true);
}

void RestEngine::appendRestStatus(std::shared_ptr<RestStatusElement> element) {
  while (element.get() != nullptr) {
    _elements.emplace_back(element);
    element = element->previous();
  }
}

// -----------------------------------------------------------------------------
// --SECTION--                                                   private methods
// -----------------------------------------------------------------------------

int RestEngine::run(std::shared_ptr<rest::RestHandler> handler, bool synchron) {
  while (true) {
    int res = TRI_ERROR_NO_ERROR;

    switch (_state) {
      case State::PREPARE:
        res = handler->prepareEngine();
        break;

      case State::EXECUTE:
        res = handler->executeEngine();
        if (res != TRI_ERROR_NO_ERROR) {
          handler->finalizeEngine();
        }
        break;

      case State::RUN:
        res = handler->runEngine(synchron);
        if (res != TRI_ERROR_NO_ERROR) {
          handler->finalizeEngine();
        }
        break;

      case State::WAITING:
        return synchron ? TRI_ERROR_INTERNAL : TRI_ERROR_NO_ERROR;

      case State::FINALIZE:
        res = handler->finalizeEngine();
        break;

      case State::DONE:
      case State::FAILED:
        return res;
    }

    if (res != TRI_ERROR_NO_ERROR) {
      return res;
    }
  }
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief console thread
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2013 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2009-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "ConsoleThread.h"

#include "ApplicationServer/ApplicationServer.h"
#include "BasicsC/logging.h"
#include "BasicsC/tri-strings.h"
#include "Rest/Version.h"
#include "VocBase/vocbase.h"
#include "V8/V8LineEditor.h"
#include "V8/v8-conv.h"
#include "V8/v8-utils.h"
#include <v8.h>

using namespace triagens::basics;
using namespace triagens::rest;
using namespace triagens::arango;

// -----------------------------------------------------------------------------
// --SECTION--                                               class ConsoleThread
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// --SECTION--                                      constructors and destructors
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a console thread
////////////////////////////////////////////////////////////////////////////////

ConsoleThread::ConsoleThread (ApplicationServer* applicationServer,
                              ApplicationV8* applicationV8,
                              TRI_vocbase_t* vocbase)
  : Thread("console"),
    _applicationServer(applicationServer),
    _applicationV8(applicationV8),
    _context(0),
    _vocbase(vocbase),
    _done(0),
    _userAborted(false) {
  allowAsynchronousCancelation();

}

////////////////////////////////////////////////////////////////////////////////
/// @brief destroys a console thread
////////////////////////////////////////////////////////////////////////////////

ConsoleThread::~ConsoleThread () {
}

// -----------------------------------------------------------------------------
// --SECTION--                                                    public methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief runs the thread
////////////////////////////////////////////////////////////////////////////////

void ConsoleThread::run () {
  usleep(100000);

  // enter V8 context
  _context = _applicationV8->enterContext(_vocbase, 0, true, true);

  try {
    inner();
    _applicationV8->exitContext(_context);
    _done = 1;
  }
  catch (...) {
    _applicationV8->exitContext(_context);
    _done = 1;

    throw;
  }
}

// -----------------------------------------------------------------------------
// --SECTION--                                                   private methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief inner thread loop - this handles all the user inputs
////////////////////////////////////////////////////////////////////////////////

void ConsoleThread::inner () {
  v8::HandleScope globalScope;

  // run the shell
  cout << "ArangoDB JavaScript emergency console (" << rest::Version::getVerboseVersionString() << ")" << endl;

  v8::Local<v8::String> name(v8::String::New("(arango)"));
  v8::Context::Scope contextScope(_context->_context);

  // .............................................................................
  // run console
  // .............................................................................

  const string pretty = "start_pretty_print();";
  TRI_ExecuteJavaScriptString(_context->_context, v8::String::New(pretty.c_str(), (int) pretty.size()), v8::String::New("(internal)"), false);

  V8LineEditor console(_context->_context, ".arangod.history");

  console.open(true);

  while (! _userAborted) {
    v8::V8::LowMemoryNotification();
    while(! v8::V8::IdleNotification()) {
    }

    char* input = console.prompt("arangod> ");

    if (_userAborted) {
      throw "user aborted";
    }

    if (input == 0) {
      _applicationServer->beginShutdown();
      _userAborted = true;

      // this will be caught by "run"
      throw "user aborted";
    }

    if (*input == '\0') {
      TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, input);
      continue;
    }

    console.addHistory(input);

    v8::HandleScope scope;
    v8::TryCatch tryCatch;

    TRI_ExecuteJavaScriptString(_context->_context, v8::String::New(input), name, true);
    TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, input);

    if (tryCatch.HasCaught()) {
      cout << TRI_StringifyV8Exception(&tryCatch);
    }
  }

  throw "user aborted";
}

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<commit_msg>fixed rethrow<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief console thread
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2013 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2009-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "ConsoleThread.h"

#include "ApplicationServer/ApplicationServer.h"
#include "BasicsC/logging.h"
#include "BasicsC/tri-strings.h"
#include "Rest/Version.h"
#include "VocBase/vocbase.h"
#include "V8/V8LineEditor.h"
#include "V8/v8-conv.h"
#include "V8/v8-utils.h"
#include <v8.h>

using namespace triagens::basics;
using namespace triagens::rest;
using namespace triagens::arango;

// -----------------------------------------------------------------------------
// --SECTION--                                               class ConsoleThread
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// --SECTION--                                      constructors and destructors
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a console thread
////////////////////////////////////////////////////////////////////////////////

ConsoleThread::ConsoleThread (ApplicationServer* applicationServer,
                              ApplicationV8* applicationV8,
                              TRI_vocbase_t* vocbase)
  : Thread("console"),
    _applicationServer(applicationServer),
    _applicationV8(applicationV8),
    _context(0),
    _vocbase(vocbase),
    _done(0),
    _userAborted(false) {
  allowAsynchronousCancelation();

}

////////////////////////////////////////////////////////////////////////////////
/// @brief destroys a console thread
////////////////////////////////////////////////////////////////////////////////

ConsoleThread::~ConsoleThread () {
}

// -----------------------------------------------------------------------------
// --SECTION--                                                    public methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief runs the thread
////////////////////////////////////////////////////////////////////////////////

void ConsoleThread::run () {
  usleep(100000);

  // enter V8 context
  _context = _applicationV8->enterContext(_vocbase, 0, true, true);

  try {
    inner();
    _applicationV8->exitContext(_context);
    _done = 1;
  }
  catch (const char*) {
    _applicationV8->exitContext(_context);
    _done = 1;
  }
  catch (...) {
    _applicationV8->exitContext(_context);
    _done = 1;

    throw;
  }
}

// -----------------------------------------------------------------------------
// --SECTION--                                                   private methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief inner thread loop - this handles all the user inputs
////////////////////////////////////////////////////////////////////////////////

void ConsoleThread::inner () {
  v8::HandleScope globalScope;

  // run the shell
  cout << "ArangoDB JavaScript emergency console (" << rest::Version::getVerboseVersionString() << ")" << endl;

  v8::Local<v8::String> name(v8::String::New("(arango)"));
  v8::Context::Scope contextScope(_context->_context);

  // .............................................................................
  // run console
  // .............................................................................

  const string pretty = "start_pretty_print();";
  TRI_ExecuteJavaScriptString(_context->_context, v8::String::New(pretty.c_str(), (int) pretty.size()), v8::String::New("(internal)"), false);

  V8LineEditor console(_context->_context, ".arangod.history");

  console.open(true);

  while (! _userAborted) {
    v8::V8::LowMemoryNotification();
    while(! v8::V8::IdleNotification()) {
    }

    char* input = console.prompt("arangod> ");

    if (_userAborted) {
      throw "user aborted";
    }

    if (input == 0) {
      _userAborted = true;
      _applicationServer->beginShutdown();

      // this will be caught by "run"
      throw "user aborted";
    }

    if (*input == '\0') {
      TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, input);
      continue;
    }

    console.addHistory(input);

    v8::HandleScope scope;
    v8::TryCatch tryCatch;

    TRI_ExecuteJavaScriptString(_context->_context, v8::String::New(input), name, true);
    TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, input);

    if (tryCatch.HasCaught()) {
      cout << TRI_StringifyV8Exception(&tryCatch);
    }
  }

  throw "user aborted";
}

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<|endoftext|>


<commit_before>#ifdef WIN32
#include "stdafx.h"
#endif

#include "ResourceManager.h"
#include <string>
#include <vector>
#ifdef __MACH__
#include <CoreFoundation/CoreFoundation.h>
#include <sys/stat.h>
#endif
#include "Logging.h"

namespace ResourceManager
{

namespace Internal
{

bool _FileExists ( const std::string& path )
{
	FILE* fp = fopen(path.c_str(), "rb");
	if (fp)
		fclose(fp);
	return fp != NULL;
}

class ResourceDomain
{
public:
	ResourceDomain () {}
	virtual ~ResourceDomain () {}

	virtual SDL_RWops* OpenFile ( const std::string& path ) = 0;
	virtual bool FileExists ( const std::string& path );
};

bool ResourceDomain::FileExists ( const std::string& path )
{
	SDL_RWops* ops = OpenFile(path);
	if (ops)
	{
		SDL_RWclose(ops);
		return true;
	}
	else
	{
		return false;
	}
}

class ResourceDomainFilesystem : public ResourceDomain
{
private:
	std::string _basePath;
public:
	ResourceDomainFilesystem ( const std::string& basePath ) : _basePath(basePath) {}
	virtual ~ResourceDomainFilesystem () {}

	virtual bool FileExists ( const std::string& path );
	virtual SDL_RWops* OpenFile ( const std::string& path );
};

bool ResourceDomainFilesystem::FileExists ( const std::string& path )
{
	std::string fullPath = _basePath + '/' + path;
	return _FileExists(fullPath);
}

SDL_RWops* ResourceDomainFilesystem::OpenFile ( const std::string& path )
{
	return SDL_RWFromFile((_basePath + '/' + path).c_str(), "rb");
}

std::vector<ResourceDomain*> searchDomains;
std::string userDirectoryPath;
SDL_mutex* mutex;

}

using namespace Internal;

// utility function for reading from a RWops in full
void* ReadFull ( size_t* length, SDL_RWops* ops, int autoclose )
{
	size_t len = SDL_RWseek(ops, 0, SEEK_END);
	*length = len;
	SDL_RWseek(ops, 0, SEEK_SET);
	void* buffer = malloc(len);
	SDL_RWread(ops, buffer, 1, len);
	if (autoclose)
		SDL_RWclose(ops);
	return buffer;
}

bool FileExists ( const std::string& name )
{
	if (name == "")
		return false;
	SDL_LockMutex(mutex);
	for (std::vector<ResourceDomain*>::iterator iter = searchDomains.begin(); iter != searchDomains.end(); iter++)
	{
		ResourceDomain* domain = *iter;
		if (domain->FileExists(name))
		{
			SDL_UnlockMutex(mutex);
			return true;
		}
	}
	SDL_UnlockMutex(mutex);
	return false;
}

static void CreateDirectoryWithIntermediates ( const std::string& dir )
{
    LOG("ResourceManager", LOG_MESSAGE, "creating directory %s with intermediates", dir.c_str());
	char cmdBuf[1024];
	sprintf(cmdBuf, "mkdir -p '%s'", dir.c_str());
	system(cmdBuf);
}

SDL_RWops* OpenFile ( const std::string& name )
{
	if (name == "")
		return NULL;
    LOG("ResourceManager", LOG_NOTICE, "Reading file: %s", name.c_str());
	SDL_LockMutex(mutex);
	for (std::vector<ResourceDomain*>::iterator iter = searchDomains.begin(); iter != searchDomains.end(); iter++)
	{
		ResourceDomain* domain = *iter;
		if (domain->FileExists(name))
		{
			SDL_RWops* ops = domain->OpenFile(name);
			SDL_UnlockMutex(mutex);
			return ops;
		}
	}
	SDL_UnlockMutex(mutex);
	return NULL;
}

SDL_RWops* WriteFile ( const std::string& name )
{
	std::string path = userDirectoryPath + '/' + name;
	CreateDirectoryWithIntermediates(path.substr(0, path.find_last_of('/')));
	return SDL_RWFromFile(path.c_str(), "wb");
}

void WriteFile ( const std::string& name, const void* data, size_t len )
{
	std::string path = userDirectoryPath + '/' + name;
	CreateDirectoryWithIntermediates(path.substr(0, path.find_last_of('/')));
	FILE* fp = fopen(path.c_str(), "rb");
	assert(fp);
	fwrite(data, 1, len, fp);
	fclose(fp);
}

void Init ( const std::string& appname )
{
#ifdef __MACH__
	char systemDirectory[1024];
	char userDirectory[1024];
	sprintf(userDirectory, "%s/Library/Application Support/%s", getenv("HOME"), appname.c_str());
	CreateDirectoryWithIntermediates(userDirectory);

	CFBundleRef mainBundle = CFBundleGetMainBundle();
	CFURLRef appResourcePath = CFBundleCopyResourcesDirectoryURL(mainBundle);
	CFURLGetFileSystemRepresentation(appResourcePath, 1, (Uint8*)systemDirectory, sizeof(systemDirectory));
	CFRelease(appResourcePath);

	searchDomains.push_back(new ResourceDomainFilesystem(userDirectory));
	searchDomains.push_back(new ResourceDomainFilesystem(systemDirectory));
	userDirectoryPath = userDirectory;
#elif defined(WIN32)
#else
	char userDirectory[1024];
	char currentDirectory[1024];
	char appShareDirectory[1024];
	sprintf(userDirectory, "%s/.%s", getenv("HOME"), appname.c_str());
	CreateDirectoryWithIntermediates(userDirectory);
	getcwd(currentDirectory);
	sprintf(appShareDirectory, "/usr/share/%s", appname.c_str());
	searchDomains.push_back(new ResourceDomainFilesystem(userDirectory));
	searchDomains.push_back(new ResourceDomainFilesystem(currentDirectory));
	searchDomains.push_back(new ResourceDomainFilesystem(shareDirectory));
#endif
	mutex = SDL_CreateMutex();
}

}
<commit_msg>Windows errors should be fixed, pushing for tests (round 5... arg).<commit_after>#ifdef WIN32
#include "stdafx.h"
#endif

#include "Apollo.h"
#include "ResourceManager.h"
#include <string>
#include <vector>
#ifdef __MACH__
#include <CoreFoundation/CoreFoundation.h>
#include <sys/stat.h>
#endif
#include "Logging.h"

namespace ResourceManager
{

namespace Internal
{

bool _FileExists ( const std::string& path )
{
	FILE* fp = fopen(path.c_str(), "rb");
	if (fp)
		fclose(fp);
	return fp != NULL;
}

class ResourceDomain
{
public:
	ResourceDomain () {}
	virtual ~ResourceDomain () {}

	virtual SDL_RWops* OpenFile ( const std::string& path ) = 0;
	virtual bool FileExists ( const std::string& path );
};

bool ResourceDomain::FileExists ( const std::string& path )
{
	SDL_RWops* ops = OpenFile(path);
	if (ops)
	{
		SDL_RWclose(ops);
		return true;
	}
	else
	{
		return false;
	}
}

class ResourceDomainFilesystem : public ResourceDomain
{
private:
	std::string _basePath;
public:
	ResourceDomainFilesystem ( const std::string& basePath ) : _basePath(basePath) {}
	virtual ~ResourceDomainFilesystem () {}

	virtual bool FileExists ( const std::string& path );
	virtual SDL_RWops* OpenFile ( const std::string& path );
};

bool ResourceDomainFilesystem::FileExists ( const std::string& path )
{
	std::string fullPath = _basePath + '/' + path;
	return _FileExists(fullPath);
}

SDL_RWops* ResourceDomainFilesystem::OpenFile ( const std::string& path )
{
	return SDL_RWFromFile((_basePath + '/' + path).c_str(), "rb");
}

std::vector<ResourceDomain*> searchDomains;
std::string userDirectoryPath;
SDL_mutex* mutex;

}

using namespace Internal;

// utility function for reading from a RWops in full
void* ReadFull ( size_t* length, SDL_RWops* ops, int autoclose )
{
	size_t len = SDL_RWseek(ops, 0, SEEK_END);
	*length = len;
	SDL_RWseek(ops, 0, SEEK_SET);
	void* buffer = malloc(len);
	SDL_RWread(ops, buffer, 1, len);
	if (autoclose)
		SDL_RWclose(ops);
	return buffer;
}

bool FileExists ( const std::string& name )
{
	if (name == "")
		return false;
	SDL_LockMutex(mutex);
	for (std::vector<ResourceDomain*>::iterator iter = searchDomains.begin(); iter != searchDomains.end(); iter++)
	{
		ResourceDomain* domain = *iter;
		if (domain->FileExists(name))
		{
			SDL_UnlockMutex(mutex);
			return true;
		}
	}
	SDL_UnlockMutex(mutex);
	return false;
}

static void CreateDirectoryWithIntermediates ( const std::string& dir )
{
    LOG("ResourceManager", LOG_MESSAGE, "creating directory %s with intermediates", dir.c_str());
	char cmdBuf[1024];
	sprintf(cmdBuf, "mkdir -p '%s'", dir.c_str());
	system(cmdBuf);
}

SDL_RWops* OpenFile ( const std::string& name )
{
	if (name == "")
		return NULL;
    LOG("ResourceManager", LOG_NOTICE, "Reading file: %s", name.c_str());
	SDL_LockMutex(mutex);
	for (std::vector<ResourceDomain*>::iterator iter = searchDomains.begin(); iter != searchDomains.end(); iter++)
	{
		ResourceDomain* domain = *iter;
		if (domain->FileExists(name))
		{
			SDL_RWops* ops = domain->OpenFile(name);
			SDL_UnlockMutex(mutex);
			return ops;
		}
	}
	SDL_UnlockMutex(mutex);
	return NULL;
}

SDL_RWops* WriteFile ( const std::string& name )
{
	std::string path = userDirectoryPath + '/' + name;
	CreateDirectoryWithIntermediates(path.substr(0, path.find_last_of('/')));
	return SDL_RWFromFile(path.c_str(), "wb");
}

void WriteFile ( const std::string& name, const void* data, size_t len )
{
	std::string path = userDirectoryPath + '/' + name;
	CreateDirectoryWithIntermediates(path.substr(0, path.find_last_of('/')));
	FILE* fp = fopen(path.c_str(), "rb");
	assert(fp);
	fwrite(data, 1, len, fp);
	fclose(fp);
}

void Init ( const std::string& appname )
{
#ifdef __MACH__
	char systemDirectory[1024];
	char userDirectory[1024];
	sprintf(userDirectory, "%s/Library/Application Support/%s", getenv("HOME"), appname.c_str());
	CreateDirectoryWithIntermediates(userDirectory);

	CFBundleRef mainBundle = CFBundleGetMainBundle();
	CFURLRef appResourcePath = CFBundleCopyResourcesDirectoryURL(mainBundle);
	CFURLGetFileSystemRepresentation(appResourcePath, 1, (Uint8*)systemDirectory, sizeof(systemDirectory));
	CFRelease(appResourcePath);

	searchDomains.push_back(new ResourceDomainFilesystem(userDirectory));
	searchDomains.push_back(new ResourceDomainFilesystem(systemDirectory));
	userDirectoryPath = userDirectory;
#elif defined(WIN32)
#else
	char userDirectory[1024];
	char currentDirectory[1024];
	char appShareDirectory[1024];
	sprintf(userDirectory, "%s/.%s", getenv("HOME"), appname.c_str());
	CreateDirectoryWithIntermediates(userDirectory);
	getcwd(currentDirectory);
	sprintf(appShareDirectory, "/usr/share/%s", appname.c_str());
	searchDomains.push_back(new ResourceDomainFilesystem(userDirectory));
	searchDomains.push_back(new ResourceDomainFilesystem(currentDirectory));
	searchDomains.push_back(new ResourceDomainFilesystem(shareDirectory));
#endif
	mutex = SDL_CreateMutex();
}

}
<|endoftext|>