<commit_before>/*

 Copyright (c) 2018, Ford Motor Company
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

 Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 Redistributions in binary form must reproduce the above copyright notice,
 this list of conditions and the following
 disclaimer in the documentation and/or other materials provided with the
 distribution.

 Neither the name of the Ford Motor Company nor the names of its contributors
 may be used to endorse or promote products derived from this software
 without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
 */

#include <algorithm>
#include "sdl_rpc_plugin/commands/mobile/put_file_request.h"

#include "application_manager/policies/policy_handler.h"
#include "application_manager/application_impl.h"
#include "application_manager/rpc_service.h"

#include "utils/file_system.h"
#include <boost/crc.hpp>

namespace {
/**
* Calculates CRC32 checksum
* @param binary_data - input data for which CRC32 should be calculated
* @return calculated CRC32 checksum
*/
uint32_t GetCrc32CheckSum(const std::vector<uint8_t>& binary_data) {
  const std::size_t file_size = binary_data.size();
  boost::crc_32_type result;
  result.process_bytes(&binary_data[0], file_size);
  return result.checksum();
}

}  // namespace

namespace sdl_rpc_plugin {
using namespace application_manager;

namespace commands {

PutFileRequest::PutFileRequest(
    const application_manager::commands::MessageSharedPtr& message,
    ApplicationManager& application_manager,
    app_mngr::rpc_service::RPCService& rpc_service,
    app_mngr::HMICapabilities& hmi_capabilities,
    policy::PolicyHandlerInterface& policy_handler)
    : CommandRequestImpl(message,
                         application_manager,
                         rpc_service,
                         hmi_capabilities,
                         policy_handler)
    , offset_(0)
    , sync_file_name_()
    , length_(0)
    , file_type_(mobile_apis::FileType::INVALID_ENUM)
    , is_persistent_file_(false) {}

PutFileRequest::~PutFileRequest() {}

void PutFileRequest::Run() {
  LOG4CXX_AUTO_TRACE(logger_);

  ApplicationSharedPtr application =
      application_manager_.application(connection_key());
  smart_objects::SmartObject response_params =
      smart_objects::SmartObject(smart_objects::SmartType_Map);

  if (!application) {
    LOG4CXX_ERROR(logger_, "Application is not registered");
    SendResponse(false, mobile_apis::Result::APPLICATION_NOT_REGISTERED);
    return;
  }

  if (mobile_api::HMILevel::HMI_NONE == application->hmi_level() &&
      application_manager_.get_settings().put_file_in_none() <=
          application->put_file_in_none_count()) {
    // If application is in the HMI_NONE level the quantity of allowed
    // PutFile request is limited by the configuration profile
    LOG4CXX_ERROR(logger_,
                  "Too many requests from the app with HMILevel HMI_NONE ");
    SendResponse(false,
                 mobile_apis::Result::REJECTED,
                 "Too many requests from the app with HMILevel HMI_NONE",
                 &response_params);
    return;
  }

  if (!(*message_)[strings::params].keyExists(strings::binary_data)) {
    LOG4CXX_ERROR(logger_, "Binary data empty");
    SendResponse(false,
                 mobile_apis::Result::INVALID_DATA,
                 "Binary data empty",
                 &response_params);
    return;
  }

  if (!(*message_)[strings::msg_params].keyExists(strings::sync_file_name)) {
    LOG4CXX_ERROR(logger_, "No file name");
    SendResponse(false,
                 mobile_apis::Result::INVALID_DATA,
                 "No file name",
                 &response_params);
    return;
  }

  if (!(*message_)[strings::msg_params].keyExists(strings::file_type)) {
    LOG4CXX_ERROR(logger_, "No file type");
    SendResponse(false,
                 mobile_apis::Result::INVALID_DATA,
                 "No file type",
                 &response_params);
    return;
  }
  sync_file_name_ =
      (*message_)[strings::msg_params][strings::sync_file_name].asString();

  if (!file_system::IsFileNameValid(sync_file_name_)) {
    const std::string err_msg = "Sync file name contains forbidden symbols.";
    LOG4CXX_ERROR(logger_, err_msg);
    SendResponse(false,
                 mobile_apis::Result::INVALID_DATA,
                 err_msg.c_str(),
                 &response_params);
    return;
  }

  file_type_ = static_cast<mobile_apis::FileType::eType>(
      (*message_)[strings::msg_params][strings::file_type].asInt());
  const std::vector<uint8_t> binary_data =
      (*message_)[strings::params][strings::binary_data].asBinary();

  // Policy table update in json format is currently to be received via PutFile
  // TODO(PV): after latest discussion has to be changed
  if (mobile_apis::FileType::JSON == file_type_) {
    policy_handler_.ReceiveMessageFromSDK(sync_file_name_, binary_data);
  }

  offset_ = 0;
  is_persistent_file_ = false;
  bool is_system_file = false;
  length_ = binary_data.size();
  bool is_download_complete = true;
  bool offset_exist =
      (*message_)[strings::msg_params].keyExists(strings::offset);

  if (offset_exist) {
    offset_ = (*message_)[strings::msg_params][strings::offset].asInt();
  }

  if ((*message_)[strings::msg_params].keyExists(strings::persistent_file)) {
    is_persistent_file_ =
        (*message_)[strings::msg_params][strings::persistent_file].asBool();
  }
  if ((*message_)[strings::msg_params].keyExists(strings::system_file)) {
    is_system_file =
        (*message_)[strings::msg_params][strings::system_file].asBool();
  }

  std::string file_path;

  if (is_system_file) {
    response_params[strings::space_available] = 0;
    file_path = application_manager_.get_settings().system_files_path();
  } else {
    file_path = application_manager_.get_settings().app_storage_folder();
    file_path += "/" + application->folder_name();

    uint32_t space_available = application->GetAvailableDiskSpace();

    if (binary_data.size() > space_available) {
      response_params[strings::space_available] =
          static_cast<uint32_t>(space_available);

      LOG4CXX_ERROR(logger_, "Out of memory");
      SendResponse(false,
                   mobile_apis::Result::OUT_OF_MEMORY,
                   "Out of memory",
                   &response_params);
      return;
    }
  }

  if (!file_system::CreateDirectoryRecursively(file_path)) {
    LOG4CXX_ERROR(logger_, "Can't create folder");
    SendResponse(false,
                 mobile_apis::Result::GENERIC_ERROR,
                 "Can't create folder.",
                 &response_params);
    return;
  }
  const std::string full_path = file_path + "/" + sync_file_name_;

  if ((*message_)[strings::msg_params].keyExists(strings::crc32_check_sum)) {
    LOG4CXX_TRACE(logger_, "Binary Data Size:  " << binary_data.size());
    const uint32_t crc_received =
        (*message_)[strings::msg_params][strings::crc32_check_sum].asUInt();
    LOG4CXX_TRACE(logger_, "CRC32 SUM Received: " << crc_received);
    const uint32_t crc_calculated = GetCrc32CheckSum(binary_data);
    LOG4CXX_TRACE(logger_, "CRC32 SUM Calculated: " << crc_calculated);
    if (crc_calculated != crc_received) {
      SendResponse(false,
                   mobile_apis::Result::CORRUPTED_DATA,
                   "CRC Check on file failed. File upload has been cancelled, "
                   "please retry.",
                   &response_params);
      return;
    }
  }

  LOG4CXX_DEBUG(logger_,
                "Writing " << binary_data.size() << " bytes to " << full_path
                           << " (current size is"
                           << file_system::FileSize(full_path) << ")");

  mobile_apis::Result::eType save_result = application_manager_.SaveBinary(
      binary_data, file_path, sync_file_name_, offset_);

  LOG4CXX_DEBUG(logger_,
                "New size of " << full_path << " is "
                               << file_system::FileSize(full_path) << " bytes");
  if (!is_system_file) {
    response_params[strings::space_available] =
        static_cast<uint32_t>(application->GetAvailableDiskSpace());
  }

  sync_file_name_ = file_path + "/" + sync_file_name_;
  switch (save_result) {
    case mobile_apis::Result::SUCCESS: {
      LOG4CXX_INFO(logger_, "PutFile is successful");
      if (!is_system_file) {
        AppFile file(sync_file_name_,
                     is_persistent_file_,
                     is_download_complete,
                     file_type_);

        if (0 == offset_) {
          LOG4CXX_INFO(logger_, "New file downloading");
          if (!application->AddFile(file)) {
            LOG4CXX_INFO(logger_,
                         "Couldn't add file to application (File already Exist"
                             << " in application and was rewritten on FS)");
            /* It can be first part of new big file, so we need to update
               information about it's downloading status and persistence */
            if (!application->UpdateFile(file)) {
              LOG4CXX_ERROR(logger_, "Couldn't update file");
              /* If it is impossible to update file, application doesn't
              know about existing this file */
              SendResponse(false,
                           mobile_apis::Result::INVALID_DATA,
                           "Couldn't update file",
                           &response_params);
              return;
            }
          } else {
            /* if file added - increment it's count
             ( may be application->AddFile have to incapsulate it? )
              Any way now this method evals not only in "none"*/
            application->increment_put_file_in_none_count();
          }
        }
      }

      SendResponse(true, save_result, "File was downloaded", &response_params);
      if (is_system_file) {
        SendOnPutFileNotification();
      }
      break;
    }
    default:
      LOG4CXX_WARN(logger_,
                   "PutFile is unsuccessful. Result = " << save_result);
      SendResponse(false, save_result, "Can't save file", &response_params);
      break;
  }
}

void PutFileRequest::SendOnPutFileNotification() {
  LOG4CXX_INFO(logger_, "SendOnPutFileNotification");
  smart_objects::SmartObjectSPtr notification =
      std::make_shared<smart_objects::SmartObject>(
          smart_objects::SmartType_Map);

  smart_objects::SmartObject& message = *notification;
  message[strings::params][strings::function_id] =
      hmi_apis::FunctionID::BasicCommunication_OnPutFile;

  message[strings::params][strings::message_type] = MessageType::kNotification;
  message[strings::msg_params][strings::app_id] = connection_key();
  message[strings::msg_params][strings::sync_file_name] = sync_file_name_;
  message[strings::msg_params][strings::offset] = offset_;
  if (0 == offset_) {
    message[strings::msg_params][strings::file_size] =
        (*message_)[strings::msg_params][strings::length];
  }
  message[strings::msg_params][strings::length] = length_;
  message[strings::msg_params][strings::persistent_file] = is_persistent_file_;
  message[strings::msg_params][strings::file_type] = file_type_;
  rpc_service_.ManageHMICommand(notification);
}

}  // namespace commands

}  // namespace application_manager
<commit_msg>Add additional check for non-manadatory parameters<commit_after>/*

 Copyright (c) 2018, Ford Motor Company
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

 Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 Redistributions in binary form must reproduce the above copyright notice,
 this list of conditions and the following
 disclaimer in the documentation and/or other materials provided with the
 distribution.

 Neither the name of the Ford Motor Company nor the names of its contributors
 may be used to endorse or promote products derived from this software
 without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
 */

#include <algorithm>
#include "sdl_rpc_plugin/commands/mobile/put_file_request.h"

#include "application_manager/policies/policy_handler.h"
#include "application_manager/application_impl.h"
#include "application_manager/rpc_service.h"

#include "utils/file_system.h"
#include <boost/crc.hpp>

namespace {
/**
* Calculates CRC32 checksum
* @param binary_data - input data for which CRC32 should be calculated
* @return calculated CRC32 checksum
*/
uint32_t GetCrc32CheckSum(const std::vector<uint8_t>& binary_data) {
  const std::size_t file_size = binary_data.size();
  boost::crc_32_type result;
  result.process_bytes(&binary_data[0], file_size);
  return result.checksum();
}

}  // namespace

namespace sdl_rpc_plugin {
using namespace application_manager;

namespace commands {

PutFileRequest::PutFileRequest(
    const application_manager::commands::MessageSharedPtr& message,
    ApplicationManager& application_manager,
    app_mngr::rpc_service::RPCService& rpc_service,
    app_mngr::HMICapabilities& hmi_capabilities,
    policy::PolicyHandlerInterface& policy_handler)
    : CommandRequestImpl(message,
                         application_manager,
                         rpc_service,
                         hmi_capabilities,
                         policy_handler)
    , offset_(0)
    , sync_file_name_()
    , length_(0)
    , file_type_(mobile_apis::FileType::INVALID_ENUM)
    , is_persistent_file_(false) {}

PutFileRequest::~PutFileRequest() {}

void PutFileRequest::Run() {
  LOG4CXX_AUTO_TRACE(logger_);

  ApplicationSharedPtr application =
      application_manager_.application(connection_key());
  smart_objects::SmartObject response_params =
      smart_objects::SmartObject(smart_objects::SmartType_Map);

  if (!application) {
    LOG4CXX_ERROR(logger_, "Application is not registered");
    SendResponse(false, mobile_apis::Result::APPLICATION_NOT_REGISTERED);
    return;
  }

  if (mobile_api::HMILevel::HMI_NONE == application->hmi_level() &&
      application_manager_.get_settings().put_file_in_none() <=
          application->put_file_in_none_count()) {
    // If application is in the HMI_NONE level the quantity of allowed
    // PutFile request is limited by the configuration profile
    LOG4CXX_ERROR(logger_,
                  "Too many requests from the app with HMILevel HMI_NONE ");
    SendResponse(false,
                 mobile_apis::Result::REJECTED,
                 "Too many requests from the app with HMILevel HMI_NONE",
                 &response_params);
    return;
  }

  if (!(*message_)[strings::params].keyExists(strings::binary_data)) {
    LOG4CXX_ERROR(logger_, "Binary data empty");
    SendResponse(false,
                 mobile_apis::Result::INVALID_DATA,
                 "Binary data empty",
                 &response_params);
    return;
  }

  if (!(*message_)[strings::msg_params].keyExists(strings::sync_file_name)) {
    LOG4CXX_ERROR(logger_, "No file name");
    SendResponse(false,
                 mobile_apis::Result::INVALID_DATA,
                 "No file name",
                 &response_params);
    return;
  }

  if (!(*message_)[strings::msg_params].keyExists(strings::file_type)) {
    LOG4CXX_ERROR(logger_, "No file type");
    SendResponse(false,
                 mobile_apis::Result::INVALID_DATA,
                 "No file type",
                 &response_params);
    return;
  }
  sync_file_name_ =
      (*message_)[strings::msg_params][strings::sync_file_name].asString();

  if (!file_system::IsFileNameValid(sync_file_name_)) {
    const std::string err_msg = "Sync file name contains forbidden symbols.";
    LOG4CXX_ERROR(logger_, err_msg);
    SendResponse(false,
                 mobile_apis::Result::INVALID_DATA,
                 err_msg.c_str(),
                 &response_params);
    return;
  }

  file_type_ = static_cast<mobile_apis::FileType::eType>(
      (*message_)[strings::msg_params][strings::file_type].asInt());
  const std::vector<uint8_t> binary_data =
      (*message_)[strings::params][strings::binary_data].asBinary();

  // Policy table update in json format is currently to be received via PutFile
  // TODO(PV): after latest discussion has to be changed
  if (mobile_apis::FileType::JSON == file_type_) {
    policy_handler_.ReceiveMessageFromSDK(sync_file_name_, binary_data);
  }

  offset_ = 0;
  is_persistent_file_ = false;
  bool is_system_file = false;
  length_ = binary_data.size();
  bool is_download_complete = true;
  bool offset_exist =
      (*message_)[strings::msg_params].keyExists(strings::offset);

  if (offset_exist) {
    offset_ = (*message_)[strings::msg_params][strings::offset].asInt();
  }

  if ((*message_)[strings::msg_params].keyExists(strings::persistent_file)) {
    is_persistent_file_ =
        (*message_)[strings::msg_params][strings::persistent_file].asBool();
  }
  if ((*message_)[strings::msg_params].keyExists(strings::system_file)) {
    is_system_file =
        (*message_)[strings::msg_params][strings::system_file].asBool();
  }

  std::string file_path;

  if (is_system_file) {
    response_params[strings::space_available] = 0;
    file_path = application_manager_.get_settings().system_files_path();
  } else {
    file_path = application_manager_.get_settings().app_storage_folder();
    file_path += "/" + application->folder_name();

    uint32_t space_available = application->GetAvailableDiskSpace();

    if (binary_data.size() > space_available) {
      response_params[strings::space_available] =
          static_cast<uint32_t>(space_available);

      LOG4CXX_ERROR(logger_, "Out of memory");
      SendResponse(false,
                   mobile_apis::Result::OUT_OF_MEMORY,
                   "Out of memory",
                   &response_params);
      return;
    }
  }

  if (!file_system::CreateDirectoryRecursively(file_path)) {
    LOG4CXX_ERROR(logger_, "Can't create folder");
    SendResponse(false,
                 mobile_apis::Result::GENERIC_ERROR,
                 "Can't create folder.",
                 &response_params);
    return;
  }
  const std::string full_path = file_path + "/" + sync_file_name_;

  if ((*message_)[strings::msg_params].keyExists(strings::crc32_check_sum)) {
    LOG4CXX_TRACE(logger_, "Binary Data Size:  " << binary_data.size());
    const uint32_t crc_received =
        (*message_)[strings::msg_params][strings::crc32_check_sum].asUInt();
    LOG4CXX_TRACE(logger_, "CRC32 SUM Received: " << crc_received);
    const uint32_t crc_calculated = GetCrc32CheckSum(binary_data);
    LOG4CXX_TRACE(logger_, "CRC32 SUM Calculated: " << crc_calculated);
    if (crc_calculated != crc_received) {
      SendResponse(false,
                   mobile_apis::Result::CORRUPTED_DATA,
                   "CRC Check on file failed. File upload has been cancelled, "
                   "please retry.",
                   &response_params);
      return;
    }
  }

  LOG4CXX_DEBUG(logger_,
                "Writing " << binary_data.size() << " bytes to " << full_path
                           << " (current size is"
                           << file_system::FileSize(full_path) << ")");

  mobile_apis::Result::eType save_result = application_manager_.SaveBinary(
      binary_data, file_path, sync_file_name_, offset_);

  LOG4CXX_DEBUG(logger_,
                "New size of " << full_path << " is "
                               << file_system::FileSize(full_path) << " bytes");
  if (!is_system_file) {
    response_params[strings::space_available] =
        static_cast<uint32_t>(application->GetAvailableDiskSpace());
  }

  sync_file_name_ = file_path + "/" + sync_file_name_;
  switch (save_result) {
    case mobile_apis::Result::SUCCESS: {
      LOG4CXX_INFO(logger_, "PutFile is successful");
      if (!is_system_file) {
        AppFile file(sync_file_name_,
                     is_persistent_file_,
                     is_download_complete,
                     file_type_);

        if (0 == offset_) {
          LOG4CXX_INFO(logger_, "New file downloading");
          if (!application->AddFile(file)) {
            LOG4CXX_INFO(logger_,
                         "Couldn't add file to application (File already Exist"
                             << " in application and was rewritten on FS)");
            /* It can be first part of new big file, so we need to update
               information about it's downloading status and persistence */
            if (!application->UpdateFile(file)) {
              LOG4CXX_ERROR(logger_, "Couldn't update file");
              /* If it is impossible to update file, application doesn't
              know about existing this file */
              SendResponse(false,
                           mobile_apis::Result::INVALID_DATA,
                           "Couldn't update file",
                           &response_params);
              return;
            }
          } else {
            /* if file added - increment it's count
             ( may be application->AddFile have to incapsulate it? )
              Any way now this method evals not only in "none"*/
            application->increment_put_file_in_none_count();
          }
        }
      }

      SendResponse(true, save_result, "File was downloaded", &response_params);
      if (is_system_file) {
        SendOnPutFileNotification();
      }
      break;
    }
    default:
      LOG4CXX_WARN(logger_,
                   "PutFile is unsuccessful. Result = " << save_result);
      SendResponse(false, save_result, "Can't save file", &response_params);
      break;
  }
}

void PutFileRequest::SendOnPutFileNotification() {
  LOG4CXX_INFO(logger_, "SendOnPutFileNotification");
  smart_objects::SmartObjectSPtr notification =
      std::make_shared<smart_objects::SmartObject>(
          smart_objects::SmartType_Map);
  smart_objects::SmartObject& message = *notification;
  message[strings::params][strings::function_id] =
      hmi_apis::FunctionID::BasicCommunication_OnPutFile;
  message[strings::params][strings::message_type] = MessageType::kNotification;
  message[strings::msg_params][strings::app_id] = connection_key();
  message[strings::msg_params][strings::sync_file_name] = sync_file_name_;
  message[strings::msg_params][strings::offset] = offset_;
  if (0 == offset_ &&
      !(*message_)[strings::msg_params].keyExists(strings::length)) {
    message[strings::msg_params][strings::file_size] = length_;
  }
  message[strings::msg_params][strings::length] = length_;
  message[strings::msg_params][strings::persistent_file] = is_persistent_file_;
  message[strings::msg_params][strings::file_type] = file_type_;
  rpc_service_.ManageHMICommand(notification);
}

}  // namespace commands

}  // namespace application_manager
<|endoftext|>


<commit_before>/*++
Copyright (c) 2012 Microsoft Corporation

Module Name:

    smt_strategic_solver.h

Abstract:

    Create a strategic solver with tactic for all main logics
    used in SMT.

Author:

    Leonardo (leonardo) 2012-02-19

Notes:

--*/
#include"cmd_context.h"
#include"combined_solver.h"
#include"tactic2solver.h"
#include"qfbv_tactic.h"
#include"qflia_tactic.h"
#include"qfnia_tactic.h"
#include"qfnra_tactic.h"
#include"qfuf_tactic.h"
#include"qflra_tactic.h"
#include"quant_tactics.h"
#include"qfauflia_tactic.h"
#include"qfaufbv_tactic.h"
#include"qfufbv_tactic.h"
#include"qfidl_tactic.h"
#include"default_tactic.h"
#include"ufbv_tactic.h"
#include"qffpa_tactic.h"
#include"horn_tactic.h"
#include"smt_solver.h"

tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const & logic) {
    if (logic=="QF_UF")
        return mk_qfuf_tactic(m, p);
    else if (logic=="QF_BV")
        return mk_qfbv_tactic(m, p);
    else if (logic=="QF_IDL")
        return mk_qfidl_tactic(m, p);
    else if (logic=="QF_LIA")
        return mk_qflia_tactic(m, p);
    else if (logic=="QF_LRA")
        return mk_qflra_tactic(m, p);
    else if (logic=="QF_NIA")
        return mk_qfnia_tactic(m, p);
    else if (logic=="QF_NRA")
        return mk_qfnra_tactic(m, p);
    else if (logic=="QF_AUFLIA")
        return mk_qfauflia_tactic(m, p);
    else if (logic=="QF_AUFBV")
        return mk_qfaufbv_tactic(m, p);
    else if (logic=="QF_ABV")
        return mk_qfaufbv_tactic(m, p);
    else if (logic=="QF_UFBV")
        return mk_qfufbv_tactic(m, p);
    else if (logic=="AUFLIA")
        return mk_auflia_tactic(m, p);
    else if (logic=="AUFLIRA")
        return mk_auflira_tactic(m, p);
    else if (logic=="AUFNIRA")
        return mk_aufnira_tactic(m, p);
    else if (logic=="UFNIA")
        return mk_ufnia_tactic(m, p);
    else if (logic=="UFLRA")
        return mk_uflra_tactic(m, p);
    else if (logic=="LRA")
        return mk_lra_tactic(m, p);
    else if (logic=="LIA")
        return mk_lia_tactic(m, p);
    else if (logic=="UFBV")
        return mk_ufbv_tactic(m, p);
    else if (logic=="BV")
        return mk_ufbv_tactic(m, p);
    else if (logic=="QF_FPA")
        return mk_qffpa_tactic(m, p);
    else if (logic=="QF_FPABV")
        return mk_qffpa_tactic(m, p);
    else if (logic=="HORN")
        return mk_horn_tactic(m, p);
    else
        return mk_default_tactic(m, p);
}

class smt_strategic_solver_factory : public solver_factory {
    symbol m_logic;
public:
    smt_strategic_solver_factory(symbol const & logic):m_logic(logic) {}

    virtual ~smt_strategic_solver_factory() {}
    virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) {
        symbol l;
        if (m_logic != symbol::null)
            l = m_logic;
        else
            l = logic;
        tactic * t = mk_tactic_for_logic(m, p, l);
        return mk_combined_solver(mk_tactic2solver(m, t, p, proofs_enabled, models_enabled, unsat_core_enabled, l),
                                  mk_smt_solver(m, p, l),
                                  p);
    }
};

solver_factory * mk_smt_strategic_solver_factory(symbol const & logic) {
    return alloc(smt_strategic_solver_factory, logic);
}

<commit_msg>sls tactic default<commit_after>/*++
Copyright (c) 2012 Microsoft Corporation

Module Name:

    smt_strategic_solver.h

Abstract:

    Create a strategic solver with tactic for all main logics
    used in SMT.

Author:

    Leonardo (leonardo) 2012-02-19

Notes:

--*/
#include"cmd_context.h"
#include"combined_solver.h"
#include"tactic2solver.h"
#include"qfbv_tactic.h"
#include"qflia_tactic.h"
#include"qfnia_tactic.h"
#include"qfnra_tactic.h"
#include"qfuf_tactic.h"
#include"qflra_tactic.h"
#include"quant_tactics.h"
#include"qfauflia_tactic.h"
#include"qfaufbv_tactic.h"
#include"qfufbv_tactic.h"
#include"qfidl_tactic.h"
#include"default_tactic.h"
#include"ufbv_tactic.h"
#include"qffpa_tactic.h"
#include"horn_tactic.h"
#include"smt_solver.h"

#include"sls_tactic.h"

tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const & logic) {
    if (logic=="QF_UF")
        return mk_qfuf_tactic(m, p);
    else if (logic=="QF_BV")
        return mk_qfbv_sls_tactic(m, p);
    else if (logic=="QF_IDL")
        return mk_qfidl_tactic(m, p);
    else if (logic=="QF_LIA")
        return mk_qflia_tactic(m, p);
    else if (logic=="QF_LRA")
        return mk_qflra_tactic(m, p);
    else if (logic=="QF_NIA")
        return mk_qfnia_tactic(m, p);
    else if (logic=="QF_NRA")
        return mk_qfnra_tactic(m, p);
    else if (logic=="QF_AUFLIA")
        return mk_qfauflia_tactic(m, p);
    else if (logic=="QF_AUFBV")
        return mk_qfaufbv_tactic(m, p);
    else if (logic=="QF_ABV")
        return mk_qfaufbv_tactic(m, p);
    else if (logic=="QF_UFBV")
        return mk_qfufbv_tactic(m, p);
    else if (logic=="AUFLIA")
        return mk_auflia_tactic(m, p);
    else if (logic=="AUFLIRA")
        return mk_auflira_tactic(m, p);
    else if (logic=="AUFNIRA")
        return mk_aufnira_tactic(m, p);
    else if (logic=="UFNIA")
        return mk_ufnia_tactic(m, p);
    else if (logic=="UFLRA")
        return mk_uflra_tactic(m, p);
    else if (logic=="LRA")
        return mk_lra_tactic(m, p);
    else if (logic=="LIA")
        return mk_lia_tactic(m, p);
    else if (logic=="UFBV")
        return mk_ufbv_tactic(m, p);
    else if (logic=="BV")
        return mk_ufbv_tactic(m, p);
    else if (logic=="QF_FPA")
        return mk_qffpa_tactic(m, p);
    else if (logic=="QF_FPABV")
        return mk_qffpa_tactic(m, p);
    else if (logic=="HORN")
        return mk_horn_tactic(m, p);
    else
        return mk_default_tactic(m, p);
}

class smt_strategic_solver_factory : public solver_factory {
    symbol m_logic;
public:
    smt_strategic_solver_factory(symbol const & logic):m_logic(logic) {}

    virtual ~smt_strategic_solver_factory() {}
    virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) {
        symbol l;
        if (m_logic != symbol::null)
            l = m_logic;
        else
            l = logic;
        tactic * t = mk_tactic_for_logic(m, p, l);
        return mk_combined_solver(mk_tactic2solver(m, t, p, proofs_enabled, models_enabled, unsat_core_enabled, l),
                                  mk_smt_solver(m, p, l),
                                  p);
    }
};

solver_factory * mk_smt_strategic_solver_factory(symbol const & logic) {
    return alloc(smt_strategic_solver_factory, logic);
}

<|endoftext|>


<commit_before>#include "helpers.hpp"
#include <chain.hpp>

#include <vector>
#include <list>
#include <string>
#include <vector>
#include <iterator>
#include <utility>

#include "catch.hpp"

using iter::chain;
using itertest::SolidInt;
using itertest::BasicIterable;
using Vec = const std::vector<char>;

TEST_CASE("chain: three strings", "[chain]") {
    std::string s1{"abc"};
    std::string s2{"mno"};
    std::string s3{"xyz"};
    auto ch = chain(s1, s2, s3);

    Vec v(std::begin(ch), std::end(ch));
    Vec vc{'a','b','c','m','n','o','x','y','z'};

    REQUIRE( v == vc );
}

TEST_CASE("chain: with different container types", "[chain]") {
    std::string s1{"abc"};
    std::list<char> li{'m', 'n', 'o'};
    std::vector<char> vec{'x', 'y', 'z'};
    auto ch = chain(s1, li, vec);

    Vec v(std::begin(ch), std::end(ch));
    Vec vc{'a','b','c','m','n','o','x','y','z'};

    REQUIRE( v == vc );
}

TEST_CASE("chain: handles empty containers", "[chain]") {
    std::string emp;
    std::string a{"a"};
    std::string b{"b"};
    std::string c{"c"};
    Vec vc{'a', 'b', 'c'};

    SECTION("Empty container at front") {
        auto ch = chain(emp, a, b, c);
        Vec v(std::begin(ch), std::end(ch));

        REQUIRE( v == vc );
    }

    SECTION("Empty container at back") {
        auto ch = chain(a, b, c, emp);
        Vec v(std::begin(ch), std::end(ch));

        REQUIRE( v == vc );
    }

    SECTION("Empty container in middle") {
        auto ch = chain(a, emp, b, emp, c);
        Vec v(std::begin(ch), std::end(ch));

        REQUIRE( v == vc );
    }

    SECTION("Consecutive empty containers at front") {
        auto ch = chain(emp, emp, a, b, c);
        Vec v(std::begin(ch), std::end(ch));

        REQUIRE( v == vc );
    }

    SECTION("Consecutive empty containers at back") {
        auto ch = chain(a, b, c, emp, emp);
        Vec v(std::begin(ch), std::end(ch));

        REQUIRE( v == vc );
    }

    SECTION("Consecutive empty containers in middle") {
        auto ch = chain(a, emp, emp, b, emp, emp, c);
        Vec v(std::begin(ch), std::end(ch));

        REQUIRE( v == vc );
    }
}

TEST_CASE("chain: with only empty containers", "[chain]") {
    std::string emp{};
    SECTION("one empty container") {
        auto ch = chain(emp);
        REQUIRE_FALSE( std::begin(ch) != std::end(ch) );
    }

    SECTION("two empty containers") {
        auto ch = chain(emp, emp);
        REQUIRE_FALSE( std::begin(ch) != std::end(ch) );
    }

    SECTION("three empty containers") {
        auto ch = chain(emp, emp, emp);
        REQUIRE_FALSE( std::begin(ch) != std::end(ch) );
    }
}

TEST_CASE("chain: doesn't move or copy elements of iterable", "[chain]") {
    constexpr SolidInt arr[] = {{6}, {7}, {8}};
    for (auto&& i : chain(arr, arr)) {
        (void)i;
    }
}

TEST_CASE("chain: binds reference to lvalue and moves rvalue", "[chain]") {
    BasicIterable<char> bi{'x', 'y', 'z'};
    BasicIterable<char> bi2{'a', 'j', 'm'};
    SECTION("First moved, second ref'd") {
        chain(std::move(bi), bi2);
        REQUIRE( bi.was_moved_from() );
        REQUIRE_FALSE( bi2.was_moved_from() );
    }
    SECTION("First ref'd, second moved") {
        chain(bi, std::move(bi2));
        REQUIRE_FALSE( bi.was_moved_from() );
        REQUIRE( bi2.was_moved_from() );
    }
}

TEST_CASE("chain: operator==", "[chain]") {
    std::string emp{};
    auto ch = chain(emp);
    REQUIRE( std::begin(ch) == std::end(ch) );
}
<commit_msg>tests chain postfix ++<commit_after>#include "helpers.hpp"
#include <chain.hpp>

#include <vector>
#include <list>
#include <string>
#include <vector>
#include <iterator>
#include <utility>

#include "catch.hpp"

using iter::chain;
using itertest::SolidInt;
using itertest::BasicIterable;
using Vec = const std::vector<char>;

TEST_CASE("chain: three strings", "[chain]") {
    std::string s1{"abc"};
    std::string s2{"mno"};
    std::string s3{"xyz"};
    auto ch = chain(s1, s2, s3);

    Vec v(std::begin(ch), std::end(ch));
    Vec vc{'a','b','c','m','n','o','x','y','z'};

    REQUIRE( v == vc );
}

TEST_CASE("chain: with different container types", "[chain]") {
    std::string s1{"abc"};
    std::list<char> li{'m', 'n', 'o'};
    std::vector<char> vec{'x', 'y', 'z'};
    auto ch = chain(s1, li, vec);

    Vec v(std::begin(ch), std::end(ch));
    Vec vc{'a','b','c','m','n','o','x','y','z'};

    REQUIRE( v == vc );
}

TEST_CASE("chain: handles empty containers", "[chain]") {
    std::string emp;
    std::string a{"a"};
    std::string b{"b"};
    std::string c{"c"};
    Vec vc{'a', 'b', 'c'};

    SECTION("Empty container at front") {
        auto ch = chain(emp, a, b, c);
        Vec v(std::begin(ch), std::end(ch));

        REQUIRE( v == vc );
    }

    SECTION("Empty container at back") {
        auto ch = chain(a, b, c, emp);
        Vec v(std::begin(ch), std::end(ch));

        REQUIRE( v == vc );
    }

    SECTION("Empty container in middle") {
        auto ch = chain(a, emp, b, emp, c);
        Vec v(std::begin(ch), std::end(ch));

        REQUIRE( v == vc );
    }

    SECTION("Consecutive empty containers at front") {
        auto ch = chain(emp, emp, a, b, c);
        Vec v(std::begin(ch), std::end(ch));

        REQUIRE( v == vc );
    }

    SECTION("Consecutive empty containers at back") {
        auto ch = chain(a, b, c, emp, emp);
        Vec v(std::begin(ch), std::end(ch));

        REQUIRE( v == vc );
    }

    SECTION("Consecutive empty containers in middle") {
        auto ch = chain(a, emp, emp, b, emp, emp, c);
        Vec v(std::begin(ch), std::end(ch));

        REQUIRE( v == vc );
    }
}

TEST_CASE("chain: with only empty containers", "[chain]") {
    std::string emp{};
    SECTION("one empty container") {
        auto ch = chain(emp);
        REQUIRE_FALSE( std::begin(ch) != std::end(ch) );
    }

    SECTION("two empty containers") {
        auto ch = chain(emp, emp);
        REQUIRE_FALSE( std::begin(ch) != std::end(ch) );
    }

    SECTION("three empty containers") {
        auto ch = chain(emp, emp, emp);
        REQUIRE_FALSE( std::begin(ch) != std::end(ch) );
    }
}

TEST_CASE("chain: doesn't move or copy elements of iterable", "[chain]") {
    constexpr SolidInt arr[] = {{6}, {7}, {8}};
    for (auto&& i : chain(arr, arr)) {
        (void)i;
    }
}

TEST_CASE("chain: binds reference to lvalue and moves rvalue", "[chain]") {
    BasicIterable<char> bi{'x', 'y', 'z'};
    BasicIterable<char> bi2{'a', 'j', 'm'};
    SECTION("First moved, second ref'd") {
        chain(std::move(bi), bi2);
        REQUIRE( bi.was_moved_from() );
        REQUIRE_FALSE( bi2.was_moved_from() );
    }
    SECTION("First ref'd, second moved") {
        chain(bi, std::move(bi2));
        REQUIRE_FALSE( bi.was_moved_from() );
        REQUIRE( bi2.was_moved_from() );
    }
}

TEST_CASE("chain: operator==", "[chain]") {
    std::string emp{};
    auto ch = chain(emp);
    REQUIRE( std::begin(ch) == std::end(ch) );
}

TEST_CASE("chain: postfix ++", "[chain]") {
    std::string s1{"a"}, s2{"b"};
    auto ch = chain(s1, s2);
    auto it = std::begin(ch);
    it++;
    REQUIRE( *it == 'b');
}

<|endoftext|>


<commit_before>#ifndef BST_HPP
#define BST_HPP
#include "BSTNode.hpp"
#include "BSTIterator.hpp"
#include <utility> // for std::pair

template<typename Data>
class BST {

protected:

  /** Pointer to the root of this BST, or nullptr if the BST is empty */
  BSTNode<Data>* root;

  /** Number of Data items stored in this BST. */
  unsigned int isize;

public:

  /** iterator is an aliased typename for BSTIterator<Data>. */
  typedef BSTIterator<Data> iterator;

  /** Default constructor.
      Initialize an empty BST.
   */
  BST() : root(nullptr), isize(0)
  {
  }

  /** Default destructor.
   *  It is virtual, to allow appropriate destruction of subclass objects.
   *  Delete every node in this BST.
   */ // TODO
  virtual ~BST()
  {
    delete (*this)->root;
  }

  /** Insert a Data item in the BST.
   *  Return a pair, with the pair's first member set to an
   *  iterator pointing to either the newly inserted element
   *  or to the equivalent element already in the set.
   *  The pair's second element is set to true
   *  if a new element was inserted or false if an
   *  equivalent element already existed.
   */ // TODO
  virtual std::pair<iterator,bool> insert(const Data& item)
  {

    return std::pair<a,b>;
  }

  /** Find a Data item in the BST.
   *  Return an iterator pointing to the item, or the end
   *  iterator if the item is not in the BST.
   */ // TODO
  iterator find(const Data& item) const
  {

  }

  /** Return the number of items currently in the BST.
   */ // TODO
  unsigned int size() const
  {
    return isize;
  }

  /** Remove all elements from this BST, and destroy them,
   *  leaving this BST with a size of 0.
   */ // TODO
  void clear()
  {

    size = 0;
  }

  /** Return true if the BST is empty, else false.
   */ // TODO
  bool empty() const
  {
    return ( size == 0 );
  }

  /** Return an iterator pointing to the first item in the BST.
   */ // TODO
  iterator begin() const {

  }

  /** Return an iterator pointing past the last item in the BST.
   */
  iterator end() const
  {
    return typename BST<Data>::iterator(nullptr);
  }

 };

#endif //BST_HPP
<commit_msg>untested begin()<commit_after>#ifndef BST_HPP
#define BST_HPP
#include "BSTNode.hpp"
#include "BSTIterator.hpp"
#include <utility> // for std::pair

template<typename Data>
class BST {

protected:

  /** Pointer to the root of this BST, or nullptr if the BST is empty */
  BSTNode<Data>* root;

  /** Number of Data items stored in this BST. */
  unsigned int isize;

public:

  /** iterator is an aliased typename for BSTIterator<Data>. */
  typedef BSTIterator<Data> iterator;

  /** Default constructor.
      Initialize an empty BST.
   */
  BST() : root(nullptr), isize(0)
  {
  }

  /** Default destructor.
   *  It is virtual, to allow appropriate destruction of subclass objects.
   *  Delete every node in this BST.
   */ // TODO
  virtual ~BST()
  {
    delete (*this)->root;
  }

  /** Insert a Data item in the BST.
   *  Return a pair, with the pair's first member set to an
   *  iterator pointing to either the newly inserted element
   *  or to the equivalent element already in the set.
   *  The pair's second element is set to true
   *  if a new element was inserted or false if an
   *  equivalent element already existed.
   */ // TODO
  virtual std::pair<iterator,bool> insert(const Data& item)
  {
    isize++;
    return std::pair<a,b>;
  }

  /** Find a Data item in the BST.
   *  Return an iterator pointing to the item, or the end
   *  iterator if the item is not in the BST.
   */ // TODO
  iterator find(const Data& item) const
  {
    BSTIterator<Data> iter = new BSTIterator<Data>((*this)->root);

  }

  /** Return the number of items currently in the BST.
   */ // TODO
  unsigned int size() const
  {
    return isize;
  }

  /** Remove all elements from this BST, and destroy them,
   *  leaving this BST with a size of 0.
   */ // TODO
  void clear()
  {

    isize = 0;
  }

  /** Return true if the BST is empty, else false.
   */ // TODO
  bool empty() const
  {
    return ( isize == 0 );
  }

  /** Return an iterator pointing to the first item in the BST.
   */ // TODO
  iterator begin() const
  {
    BSTNode<Data> temp = ( (*this)->root );
    while (temp->left)
      temp = temp->left;

    return new BSTIterator<Data>(temp);
  }

  /** Return an iterator pointing past the last item in the BST.
   */
  iterator end() const
  {
    return typename BST<Data>::iterator(nullptr);
  }

 };

#endif //BST_HPP
<|endoftext|>


<commit_before>/*
 * NormalizedMutualInformation.cpp
 *
 *  Created on: 30.04.2013
 *      Author: cls
 */

#include "NMIDistance.h"

namespace NetworKit {

NMIDistance::NMIDistance() {
	// TODO Auto-generated constructor stub

}

NMIDistance::~NMIDistance() {
	// TODO Auto-generated destructor stub
}

double NMIDistance::getDissimilarity(Graph& G, Clustering& zeta, Clustering& eta) {

	count n = G.numberOfNodes();

	std::vector<count> size_zeta(zeta.upperBound());
	std::vector<count> size_eta(eta.upperBound());

	// precompute sizes for each cluster

	G.forNodes([&](node u){
		cluster C = zeta[u];
		cluster D = eta[u];
		assert (C != none);
		assert (D != none);
		size_zeta[C] += 1;
		size_eta[D] += 1;
	});

	DEBUG("size_zeta=" << Aux::vectorToString(size_zeta));
	DEBUG("size_eta=" << Aux::vectorToString(size_eta));

	// precompute cluster probabilities
	std::vector<double> P_zeta(zeta.upperBound(), 0.0);
	std::vector<double> P_eta(eta.upperBound(), 0.0);

	for (cluster C = zeta.lowerBound(); C < zeta.upperBound(); ++C) {
		P_zeta[C] = size_zeta[C] / (double) n;
	}

	for (cluster C = eta.lowerBound(); C < eta.upperBound(); ++C) {
		P_eta[C] = size_eta[C] / (double) n;
	}

	HashingOverlapper hashing;
	std::vector<Clustering> clusterings;
	clusterings.push_back(zeta);
	clusterings.push_back(eta);

	Clustering overlap = hashing.run(G, clusterings);
	DEBUG("overlap=" << Aux::vectorToString(overlap.getVector()));

	std::vector<std::vector<cluster> > intersect(zeta.upperBound(), std::vector<cluster>(eta.upperBound(), none)); // intersect[C][D] returns the overlap cluster

	std::vector<count> overlapSizes(overlap.upperBound(), 0); // overlapSizes[O] returns the size of the overlap cluster

	G.forNodes([&](node u){
		cluster O = overlap[u];
		cluster C = zeta[u];
		cluster D = eta[u];
		intersect[C][D] = O; // writes are redundant - but this may be efficient
		overlapSizes[O] += 1;
	});

	/**
	 * Return the size of the union of C and D.
	 * C is a cluster in zeta, D in eta
	 */
	auto unionSize = [&](cluster C, cluster D){
		cluster inter = intersect[C][D];
		assert (inter != none); // entry must be set
		TRACE("clusters sized " << size_zeta[C] << " and " << size_eta[D] << " have overlap of " << overlapSizes[inter]);
		assert (overlapSizes[inter] >= 0);
		assert (overlapSizes[inter] <= std::max(size_zeta[C], size_eta[D]));
		return size_zeta[C] + size_eta[D] - overlapSizes[inter];
	};

	auto log_b = Aux::MissingMath::log_b; // import convenient logarithm function

	// calculate mutual information
	//		 $MI(\zeta,\eta):=\sum_{C\in\zeta}\sum_{D\in\eta}\frac{|C\cap D|}{n}\cdot\log_{2}\left(\frac{|C\cup D|\cdot n}{|C|\cdot|D|}\right)$
	double MI = 0.0; // mutual information
	for (cluster C = 0; C < zeta.upperBound(); C++) {
		for (cluster D = 0; D < eta.upperBound(); D++) {
			count sizeC = size_zeta[C];
			count sizeD = size_eta[D];
			if ((sizeC != 0) && (sizeD != 0)) {
				double factor1 = overlapSizes[intersect[C][D]] / (double) n;
				assert ((size_zeta[C] * size_eta[D]) != 0);
				TRACE("union of " << C << " and " << D << ": " << unionSize(C, D));
				double frac2 = (unionSize(C, D) * n) / (size_zeta[C] * size_eta[D]);
				double factor2 = log_b(frac2, 2);
				MI += factor1 * factor2;
			}
		}
	}

	// sanity check
	assert (! std::isnan(MI));
	assert (MI >= 0.0);
	assert (MI <= 1.0);

	// compute entropy for both clusterings
	// $H(\zeta):=-\sum_{C\in\zeta}P(C)\cdot\log_{2}(P(C))$
	double H_zeta = 0.0;
	for (cluster C = zeta.lowerBound(); C< zeta.upperBound(); ++C) {
		if (P_zeta[C] != 0) {
			H_zeta += P_zeta[C] * log_b(P_zeta[C], 2);
		} // log(0) is not defined
	}
	H_zeta = -1.0 * H_zeta;

	double H_eta = 0.0;
	for (cluster C = zeta.lowerBound(); C< zeta.upperBound(); ++C) {
		if (P_zeta[C] != 0) {
			H_eta += P_eta[C] * log_b(P_eta[C], 2);
		} // log(0) is not defined
	}
	H_eta = -1.0 * H_eta;

	assert (! std::isnan(H_zeta));
	assert (! std::isnan(H_eta));

	// entropy values range from 0 for the 1-clustering to log_2(n) for the singleton clustering
	assert (H_zeta >= 0.0);
	assert (H_eta >= 0.0);
	assert (H_zeta <= log_b(n, 2));
	assert (H_zeta <= log_b(n, 2));

	// calculate NMID
	// $NMI(\zeta,\eta):=\frac{2\cdot MI(\zeta,\eta)}{H(\zeta)+H\text{(\eta)}}$
	// $NMID(\zeta,\eta):=\begin{cases}
	//	1-NMI(\zeta,\eta)\\
	//	0 & H(\zeta)+H(\eta)=0
	//	\end{cases}$$
	double NMID;
	double NMI;
	if ((H_zeta + H_eta) == 0) {
		NMID = 0.0;
	} else {
		NMI = (2 * MI) / (H_zeta + H_eta);
		NMID = 1.0 - NMI;
	}
	// sanity check
	assert (NMID >= 0.0);
	assert (NMID <= 1.0);
	return NMID;

}

} /* namespace NetworKit */
<commit_msg>debugged NMIDistance<commit_after>/*
 * NormalizedMutualInformation.cpp
 *
 *  Created on: 30.04.2013
 *      Author: cls
 */

#include "NMIDistance.h"

namespace NetworKit {

NMIDistance::NMIDistance() {
	// TODO Auto-generated constructor stub

}

NMIDistance::~NMIDistance() {
	// TODO Auto-generated destructor stub
}

double NMIDistance::getDissimilarity(Graph& G, Clustering& zeta, Clustering& eta) {

	count n = G.numberOfNodes();

	std::vector<count> size_zeta(zeta.upperBound());
	std::vector<count> size_eta(eta.upperBound());

	// precompute sizes for each cluster

	G.forNodes([&](node u){
		cluster C = zeta[u];
		cluster D = eta[u];
		assert (C != none);
		assert (D != none);
		size_zeta[C] += 1;
		size_eta[D] += 1;
	});

	DEBUG("size_zeta=" << Aux::vectorToString(size_zeta));
	DEBUG("size_eta=" << Aux::vectorToString(size_eta));

	// precompute cluster probabilities
	std::vector<double> P_zeta(zeta.upperBound(), 0.0);
	std::vector<double> P_eta(eta.upperBound(), 0.0);

	for (cluster C = zeta.lowerBound(); C < zeta.upperBound(); ++C) {
		P_zeta[C] = size_zeta[C] / (double) n;
	}

	for (cluster C = eta.lowerBound(); C < eta.upperBound(); ++C) {
		P_eta[C] = size_eta[C] / (double) n;
	}

	HashingOverlapper hashing;
	std::vector<Clustering> clusterings;
	clusterings.push_back(zeta);
	clusterings.push_back(eta);

	Clustering overlap = hashing.run(G, clusterings);
	DEBUG("overlap=" << Aux::vectorToString(overlap.getVector()));

	std::vector<std::vector<cluster> > intersect(zeta.upperBound(), std::vector<cluster>(eta.upperBound(), none)); // intersect[C][D] returns the overlap cluster

	std::vector<count> overlapSizes(overlap.upperBound(), 0); // overlapSizes[O] returns the size of the overlap cluster

	G.forNodes([&](node u){
		cluster O = overlap[u];
		cluster C = zeta[u];
		cluster D = eta[u];
		intersect[C][D] = O; // writes are redundant - but this may be efficient
		overlapSizes[O] += 1;
	});

	/**
	 * Return the size of the union of C and D.
	 * C is a cluster in zeta, D in eta
	 */
	auto unionSize = [&](cluster C, cluster D){
		cluster inter = intersect[C][D];
		assert (inter != none); // entry must be set
		TRACE("clusters sized " << size_zeta[C] << " and " << size_eta[D] << " have overlap of " << overlapSizes[inter]);
		assert (overlapSizes[inter] >= 0);
		assert (overlapSizes[inter] <= std::max(size_zeta[C], size_eta[D]));
		return size_zeta[C] + size_eta[D] - overlapSizes[inter];
	};

	auto log_b = Aux::MissingMath::log_b; // import convenient logarithm function

	// calculate mutual information
	//		 $MI(\zeta,\eta):=\sum_{C\in\zeta}\sum_{D\in\eta}\frac{|C\cap D|}{n}\cdot\log_{2}\left(\frac{|C\cup D|\cdot n}{|C|\cdot|D|}\right)$
	double MI = 0.0; // mutual information
	for (cluster C = 0; C < zeta.upperBound(); C++) {
		for (cluster D = 0; D < eta.upperBound(); D++) {
			count sizeC = size_zeta[C];
			count sizeD = size_eta[D];
			if ((sizeC != 0) && (sizeD != 0)) { // cluster ids may not correspond to a real cluster
				// the two clusters may or may not intersect
				cluster inter = intersect[C][D];
				if (inter == none) { // clusters do not intersect
					TRACE("clusters do not intersect: " << C << ", " << D);
				} else {
					double factor1 = overlapSizes[inter] / (double) n;
					assert ((size_zeta[C] * size_eta[D]) != 0);
					TRACE("union of " << C << " and " << D << " has size: " << unionSize(C, D));
					TRACE("overlap of " << C << " and " << D << " has size: " << overlapSizes[inter]);
					double frac2 = (overlapSizes[inter] * n) / (size_zeta[C] * size_eta[D]);
					double factor2 = log_b(frac2, 2);
					TRACE("frac2 = " << frac2 << ", factor1 = " << factor1 << ", factor2 = " << factor2);
					MI += factor1 * factor2;
				}
			}
		}
	}

	// sanity check
	assert (! std::isnan(MI));
	assert (MI >= 0.0);

	// compute entropy for both clusterings
	// $H(\zeta):=-\sum_{C\in\zeta}P(C)\cdot\log_{2}(P(C))$
	double H_zeta = 0.0;
	for (cluster C = zeta.lowerBound(); C< zeta.upperBound(); ++C) {
		if (P_zeta[C] != 0) {
			H_zeta += P_zeta[C] * log_b(P_zeta[C], 2);
		} // log(0) is not defined
	}
	H_zeta = -1.0 * H_zeta;

	double H_eta = 0.0;
	for (cluster C = zeta.lowerBound(); C< zeta.upperBound(); ++C) {
		if (P_zeta[C] != 0) {
			H_eta += P_eta[C] * log_b(P_eta[C], 2);
		} // log(0) is not defined
	}
	H_eta = -1.0 * H_eta;

	assert (! std::isnan(H_zeta));
	assert (! std::isnan(H_eta));

	// entropy values range from 0 for the 1-clustering to log_2(n) for the singleton clustering
	assert (H_zeta >= 0.0);
	assert (H_eta >= 0.0);
	assert (H_zeta <= log_b(n, 2));
	assert (H_zeta <= log_b(n, 2));

	// calculate NMID
	// $NMI(\zeta,\eta):=\frac{2\cdot MI(\zeta,\eta)}{H(\zeta)+H\text{(\eta)}}$
	// $NMID(\zeta,\eta):=\begin{cases}
	//	1-NMI(\zeta,\eta)\\
	//	0 & H(\zeta)+H(\eta)=0
	//	\end{cases}$$
	double NMID;
	double NMI;
	if ((H_zeta + H_eta) == 0) {
		NMID = 0.0;
	} else {
		NMI = (2 * MI) / (H_zeta + H_eta);
		NMID = 1.0 - NMI;
	}
	// sanity check
	// assert (NMID >= 0.0);
	assert (NMID <= 1.0);
	return NMID;

}

} /* namespace NetworKit */
<|endoftext|>


<commit_before>
// libPowerUP - Create games with SDL2 and OpenGL
// Copyright(c) 2015, Erik Edlund <erik.edlund@32767.se>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with
// or without modification, are permitted provided that the
// following conditions are met:
//
// 1. Redistributions of source code must retain the above
//    copyright notice, this list of conditions and the
//    following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above
//    copyright notice, this list of conditions and the
//    following disclaimer in the documentation and / or
//    other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names
//    of its contributors may be used to endorse or promote
//    products derived from this software without specific
//    prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.

#include "pup_snd.h"

namespace pup {
namespace snd {

sound::sound(const boost::filesystem::path& path) :
	chunk_(::Mix_LoadWAV(path.string().c_str()))
{
	if (!chunk_) {
		PUP_ERR(std::runtime_error, boost::str(boost::format(
			"failed to load file \"%1%\""
		) % path));
	}
}

sound::~sound() throw()
{
	::Mix_FreeChunk(chunk_);
}

bool sound::play(int channel, int loop) throw()
{
	return ::Mix_PlayChannel(channel, chunk_, loop) != -1;
}

soundboard::soundboard()
{
}

soundboard::~soundboard() throw()
{
}

void soundboard::load_file(const boost::filesystem::path& path, const std::string& name)
{
	if (!sounds_.insert(sound_map::value_type(
		name,
		sound_ptr(new sound(path)))
	).second) {
		PUP_ERR(std::runtime_error, boost::str(boost::format(
			"name collision, sound with name \"%1%\" already exist"
		) % name));
	}
}

bool soundboard::play(const std::string& name, int channel, int loop)
{
	auto it = sounds_.find(name);
	if (it != sounds_.end()) {
		return it->second->play(channel, loop);
	}
	return false;
}

music::music() :
	track_(nullptr)
{
}

music::~music() throw()
{
	this->stop();
}

void music::start(const boost::filesystem::path& path, int repeat, int fadein)
{
	this->stop();

	if (!boost::filesystem::is_regular_file(path))
		PUP_ERR(std::runtime_error, "given path is not a file");

	if (!(track_ = ::Mix_LoadMUS(path.string().c_str())))
		PUP_ERR(std::runtime_error, ::Mix_GetError());

	::Mix_FadeInMusic(track_, repeat, fadein);
}

void music::stop() throw()
{
	if (track_) {
		::Mix_HaltMusic();
		::Mix_FreeMusic(track_);
		track_ = nullptr;
	}
}

bool music::playing() const throw()
{
	return ::Mix_PlayingMusic() == 1;
}

void music::fadeout(int duration) throw()
{
	if (track_) {
		::Mix_FadeOutMusic(duration);
	}
}

void music::set_volume(int volume)
{
	::Mix_VolumeMusic(volume);
}

int music::get_volume() const throw()
{
	return ::Mix_VolumeMusic(-1);
}

jukebox::jukebox() :
	running_(false),
	random_(false),
	history_lim_(3)
{
	track_ = files_.end();
}

jukebox::~jukebox() throw()
{
}

::Uint32 jukebox::load_dir(const boost::filesystem::path& dir)
{
	if (!boost::filesystem::is_directory(dir)) {
		PUP_ERR(std::runtime_error, boost::str(boost::format(
			"path \"%1%\" is not a directory") % dir.string()
		));
	}
	files_.clear();
	std::copy(
		boost::filesystem::directory_iterator(dir),
		boost::filesystem::directory_iterator(),
		std::back_inserter(files_)
	);
	return this->filter_files();
}

::Uint32 jukebox::load_files(const io::path_list& files)
{
	track_ = files_.end();
	history_.clear();
	files_.clear();
	std::copy(
		files.begin(),
		files.end(),
		std::back_inserter(files_)
	);
	return this->filter_files();
}

void jukebox::update(music& mus)
{
	if (running_ && !mus.playing() && !files_.empty()) {
		if (random_) {
			io::path_list::iterator it;
			do {
				it = pup::random_element(files_.begin(), files_.end());
				//for (auto jit : files_) std::cout << jit << std::endl;
			} while (std::find(history_.begin(), history_.end(), *it) != history_.end());
			mus.start(*it);
			history_.push_back(*it);
			if (static_cast<int>(history_.size()) == history_lim_) {
				history_.pop_front();
			}
			track_ = it;
		} else {
			if (track_ == files_.end()) {
				track_ = files_.begin();
			}
			auto it = track_++;
			mus.start(*it);
		}
	}
}

::Uint32 jukebox::filter_files()
{
	for (auto it = files_.begin(); it != files_.end(); /* in-loop */) {
		if (
			boost::filesystem::is_regular_file(*it) &&
			it->extension().string() == ".wav"
		) {
			++it;
		} else {
			it = files_.erase(it);
		}
	}
	return files_.size();
}

} // snd
} // pup
<commit_msg>Allow the jukebox to play wav, mp3 and ogg.<commit_after>
// libPowerUP - Create games with SDL2 and OpenGL
// Copyright(c) 2015, Erik Edlund <erik.edlund@32767.se>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with
// or without modification, are permitted provided that the
// following conditions are met:
//
// 1. Redistributions of source code must retain the above
//    copyright notice, this list of conditions and the
//    following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above
//    copyright notice, this list of conditions and the
//    following disclaimer in the documentation and / or
//    other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names
//    of its contributors may be used to endorse or promote
//    products derived from this software without specific
//    prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.

#include "pup_snd.h"

namespace pup {
namespace snd {

sound::sound(const boost::filesystem::path& path) :
	chunk_(::Mix_LoadWAV(path.string().c_str()))
{
	if (!chunk_) {
		PUP_ERR(std::runtime_error, boost::str(boost::format(
			"failed to load file \"%1%\""
		) % path));
	}
}

sound::~sound() throw()
{
	::Mix_FreeChunk(chunk_);
}

bool sound::play(int channel, int loop) throw()
{
	return ::Mix_PlayChannel(channel, chunk_, loop) != -1;
}

soundboard::soundboard()
{
}

soundboard::~soundboard() throw()
{
}

void soundboard::load_file(const boost::filesystem::path& path, const std::string& name)
{
	if (!sounds_.insert(sound_map::value_type(
		name,
		sound_ptr(new sound(path)))
	).second) {
		PUP_ERR(std::runtime_error, boost::str(boost::format(
			"name collision, sound with name \"%1%\" already exist"
		) % name));
	}
}

bool soundboard::play(const std::string& name, int channel, int loop)
{
	auto it = sounds_.find(name);
	if (it != sounds_.end()) {
		return it->second->play(channel, loop);
	}
	return false;
}

music::music() :
	track_(nullptr)
{
}

music::~music() throw()
{
	this->stop();
}

void music::start(const boost::filesystem::path& path, int repeat, int fadein)
{
	this->stop();

	if (!boost::filesystem::is_regular_file(path))
		PUP_ERR(std::runtime_error, "given path is not a file");

	if (!(track_ = ::Mix_LoadMUS(path.string().c_str())))
		PUP_ERR(std::runtime_error, ::Mix_GetError());

	::Mix_FadeInMusic(track_, repeat, fadein);
}

void music::stop() throw()
{
	if (track_) {
		::Mix_HaltMusic();
		::Mix_FreeMusic(track_);
		track_ = nullptr;
	}
}

bool music::playing() const throw()
{
	return ::Mix_PlayingMusic() == 1;
}

void music::fadeout(int duration) throw()
{
	if (track_) {
		::Mix_FadeOutMusic(duration);
	}
}

void music::set_volume(int volume)
{
	::Mix_VolumeMusic(volume);
}

int music::get_volume() const throw()
{
	return ::Mix_VolumeMusic(-1);
}

jukebox::jukebox() :
	running_(false),
	random_(false),
	history_lim_(3)
{
	track_ = files_.end();
}

jukebox::~jukebox() throw()
{
}

::Uint32 jukebox::load_dir(const boost::filesystem::path& dir)
{
	if (!boost::filesystem::is_directory(dir)) {
		PUP_ERR(std::runtime_error, boost::str(boost::format(
			"path \"%1%\" is not a directory") % dir.string()
		));
	}
	files_.clear();
	std::copy(
		boost::filesystem::directory_iterator(dir),
		boost::filesystem::directory_iterator(),
		std::back_inserter(files_)
	);
	return this->filter_files();
}

::Uint32 jukebox::load_files(const io::path_list& files)
{
	track_ = files_.end();
	history_.clear();
	files_.clear();
	std::copy(
		files.begin(),
		files.end(),
		std::back_inserter(files_)
	);
	return this->filter_files();
}

void jukebox::update(music& mus)
{
	if (running_ && !mus.playing() && !files_.empty()) {
		if (random_) {
			io::path_list::iterator it;
			do {
				it = pup::random_element(files_.begin(), files_.end());
			} while (std::find(history_.begin(), history_.end(), *it) != history_.end());
			mus.start(*it);
			history_.push_back(*it);
			if (static_cast<int>(history_.size()) == history_lim_) {
				history_.pop_front();
			}
			track_ = it;
		} else {
			if (track_ == files_.end()) {
				track_ = files_.begin();
			}
			auto it = track_++;
			mus.start(*it);
		}
	}
}

::Uint32 jukebox::filter_files()
{
	for (auto it = files_.begin(); it != files_.end(); /* in-loop */) {
		if (
			boost::filesystem::is_regular_file(*it) && (
				it->extension().string() == ".mp3" ||
				it->extension().string() == ".ogg" ||
				it->extension().string() == ".wav"
			)
		) {
			++it;
		} else {
			it = files_.erase(it);
		}
	}
	return files_.size();
}

} // snd
} // pup
<|endoftext|>


<commit_before>
#include <chrono>
#include <iostream>
#include <fstream>

#include "RMDP.hpp"

using namespace std;
using namespace craam;

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

    if(argc != 2){
        cout << "Invalid execution parameters. Execute as: " << endl;
        cout << argv[0] << " mdp_file " << endl;
        return -1;
    }

    string filename = argv[1];

    cout << "loading" << endl;

    ifstream ifs;
    ifs.open(filename);
    if(!ifs.is_open()){
        cout << "file could not be open";
        return -1;
    }
    auto rmdp = RMDP::transitions_from_csv(ifs,true);
    ifs.close();

    cout << "running test" << endl;

    auto start = std::chrono::high_resolution_clock::now();

    //#include <gperftools/profiler.h>
    // library option -lprofiler
    //ProfilerStart("mpi.prof");

    vector<prec_t> value(rmdp->state_count());
    auto&& sol = rmdp->mpi_jac_rob(value,0.999,2000,0.0001,2000,0.0001);

    //ProfilerStop();

    auto finish = std::chrono::high_resolution_clock::now();

    cout << "done." <<endl;
    cout << "Iterations: " << sol.iterations <<  ", Residual: " << sol.residual << endl;

    std::cout << "Duration:  *** " << std::chrono::duration_cast<std::chrono::milliseconds>(finish-start).count() << "ms *** \n";
}
<commit_msg>Fixed a problem with the benchmark<commit_after>
#include <chrono>
#include <iostream>
#include <fstream>

#include "RMDP.hpp"

using namespace std;
using namespace craam;

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

    if(argc != 2){
        cout << "Invalid execution parameters. Execute as: " << endl;
        cout << argv[0] << " mdp_file " << endl;
        return -1;
    }

    string filename = argv[1];

    cout << "loading" << endl;

    ifstream ifs;
    ifs.open(filename);
    if(!ifs.is_open()){
        cout << "file could not be open";
        return -1;
    }
    auto rmdp = RMDP::from_csv(ifs,true);
    ifs.close();

    cout << "running test" << endl;

    auto start = std::chrono::high_resolution_clock::now();

    //#include <gperftools/profiler.h>
    // library option -lprofiler
    //ProfilerStart("mpi.prof");

    vector<prec_t> value(rmdp->state_count());
    auto&& sol = rmdp->mpi_jac_rob(value,0.999,2000,0.0001,2000,0.0001);

    //ProfilerStop();

    auto finish = std::chrono::high_resolution_clock::now();

    cout << "done." <<endl;
    cout << "Iterations: " << sol.iterations <<  ", Residual: " << sol.residual << endl;

    std::cout << "Duration:  *** " << std::chrono::duration_cast<std::chrono::milliseconds>(finish-start).count() << "ms *** \n";
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * X testing environment - Google Test environment feat. dummy x server
 *
 * Copyright (C) 2011 Canonical Ltd.
 *
 * 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 "xorg/gtest/environment.h"
#include "xorg/gtest/process.h"

#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

#include <cstring>
#include <iostream>

#include <X11/Xlib.h>

struct xorg::testing::Environment::Private {
  std::string path_to_conf;
  int display;
  Process process;
};

xorg::testing::Environment::Environment(const std::string& path, int display)
    : d_(new Private) {
  d_->path_to_conf = path;
  d_->display = display;
}

xorg::testing::Environment::~Environment() {
  delete d_;
}

void xorg::testing::Environment::SetUp() {
  static char display_string[6];
  snprintf(display_string, 6, ":%d", d_->display);

  if (d_->process.Start("Xorg", display_string, d_->path_to_conf.c_str())) {
    setenv("DISPLAY", display_string, true);

    for (int i = 0; i < 10; /*++i*/) {
      Display* display = XOpenDisplay(NULL);

      if (display) {
        XCloseDisplay(display);
        return;
      }

      int status;
      int pid = d_->process.Wait(&status, WNOHANG); //waitpid(d_->child_pid_, &status, WNOHANG);
      if (pid == d_->process.pid()) {
        // d_->child_pid_ = -1;
        FAIL() << "Dummy X server failed to start, did you run as root?";
        return;
      } else if (pid == 0) {
        sleep(1); /* Give the dummy X server some time to start */
        continue;
      } else if (pid == -1) {
        FAIL() << "Could not get status of dummy X server process: "
            << std::strerror(errno);
        return;
      } else {
        FAIL() << "Invalid child PID returned by waitpid()";
        return;
      }
    }

    FAIL() << "Unable to open connection to dummy X server";
  }

#if 0
  d_->child_pid_ = vfork();
  if (d_->child_pid_ == -1) {
    FAIL() << "Failed to fork a process for dummy X server: "
    << std::strerror(errno);
  } else if (!d_->child_pid_) { /* Child */
    close(0);
    close(1);
    close(2);

    execlp("Xorg", "Xorg", display_string, "-config", d_->path_to_conf_.c_str(),
        NULL);
    perror("Failed to start dummy X server");
    exit(-1);
  } else { /* Parent */
    setenv("DISPLAY", display_string, true);

    for (int i = 0; i < 10; /*++i*/) {
      Display* display = XOpenDisplay(NULL);

      if (display) {
        XCloseDisplay(display);
        return;
      }

      int status;
      int pid = waitpid(d_->child_pid_, &status, WNOHANG);
      if (pid == d_->child_pid_) {
        d_->child_pid_ = -1;
        FAIL() << "Dummy X server failed to start, did you run as root?";
        return;
      } else if (pid == 0) {
        sleep(1); /* Give the dummy X server some time to start */
        continue;
      } else if (pid == -1) {
        FAIL() << "Could not get status of dummy X server process: "
        << std::strerror(errno);
        return;
      } else {
        FAIL() << "Invalid child PID returned by waitpid()";
        return;
      }
    }

    FAIL() << "Unable to open connection to dummy X server";
  }
#endif
}

void xorg::testing::Environment::TearDown() {
  if (!d_->process.Terminate()) {
    FAIL() << "Warning: Failed to terminate dummy Xorg server: "
        << std::strerror(errno);
    if (!d_->process.Kill())
      FAIL() << "Warning: Failed to kill dummy Xorg server: "
          << std::strerror(errno);
  }
#if 0
  if (d_->child_pid_ && d_->child_pid_ != -1) {
    if (kill(d_->child_pid_, SIGTERM) < 0) {
      FAIL() << "Warning: Failed to terminate dummy Xorg server: "
      << std::strerror(errno);
      if (kill(d_->child_pid_, SIGKILL))
      FAIL() << "Warning: Failed to kill dummy Xorg server: "
      << std::strerror(errno);
    }
  }
#endif
}
<commit_msg>Remove dead code in Environment<commit_after>/*****************************************************************************
 *
 * X testing environment - Google Test environment feat. dummy x server
 *
 * Copyright (C) 2011 Canonical Ltd.
 *
 * 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 "xorg/gtest/environment.h"
#include "xorg/gtest/process.h"

#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

#include <cstring>
#include <iostream>

#include <X11/Xlib.h>

struct xorg::testing::Environment::Private {
  std::string path_to_conf;
  int display;
  Process process;
};

xorg::testing::Environment::Environment(const std::string& path, int display)
    : d_(new Private) {
  d_->path_to_conf = path;
  d_->display = display;
}

xorg::testing::Environment::~Environment() {
  delete d_;
}

void xorg::testing::Environment::SetUp() {
  static char display_string[6];
  snprintf(display_string, 6, ":%d", d_->display);

  if (d_->process.Start("Xorg", display_string, d_->path_to_conf.c_str())) {
    setenv("DISPLAY", display_string, true);

    for (int i = 0; i < 10; /*++i*/) {
      Display* display = XOpenDisplay(NULL);

      if (display) {
        XCloseDisplay(display);
        return;
      }

      int status;
      int pid = d_->process.Wait(&status, WNOHANG);
      if (pid == d_->process.pid()) {
        FAIL() << "Dummy X server failed to start, did you run as root?";
        return;
      } else if (pid == 0) {
        sleep(1); /* Give the dummy X server some time to start */
        continue;
      } else if (pid == -1) {
        FAIL() << "Could not get status of dummy X server process: "
            << std::strerror(errno);
        return;
      } else {
        FAIL() << "Invalid child PID returned by waitpid()";
        return;
      }
    }

    FAIL() << "Unable to open connection to dummy X server";
  }
}

void xorg::testing::Environment::TearDown() {
  if (!d_->process.Terminate()) {
    FAIL() << "Warning: Failed to terminate dummy Xorg server: "
        << std::strerror(errno);
    if (!d_->process.Kill())
      FAIL() << "Warning: Failed to kill dummy Xorg server: "
          << std::strerror(errno);
  }
}
<|endoftext|>