<commit_before>//*****************************************************************************
// Copyright 2017-2019 Intel Corporation
//
// 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.
//*****************************************************************************

#pragma once

#include <exception>
#include <iomanip>
#include <iostream>
#include <list>
#include <memory>
#include <random>

#include "ngraph/descriptor/layout/tensor_layout.hpp"
#include "ngraph/file_util.hpp"
#include "ngraph/log.hpp"
#include "ngraph/runtime/backend.hpp"
#include "ngraph/runtime/tensor.hpp"
#include "ngraph/serializer.hpp"

namespace ngraph
{
    class Node;
    class Function;
}

bool validate_list(const std::list<std::shared_ptr<ngraph::Node>>& nodes);
std::shared_ptr<ngraph::Function> make_test_graph();
std::shared_ptr<ngraph::Function> make_function_from_file(const std::string& file_name);

template <typename T>
void copy_data(std::shared_ptr<ngraph::runtime::Tensor> tv, const std::vector<T>& data)
{
    size_t data_size = data.size() * sizeof(T);
    tv->write(data.data(), 0, data_size);
}

template <typename T>
std::vector<T> read_vector(std::shared_ptr<ngraph::runtime::Tensor> tv)
{
    if (ngraph::element::from<T>() != tv->get_tensor_layout()->get_element_type())
    {
        throw std::invalid_argument("read_vector type must match Tensor type");
    }
    size_t element_count = ngraph::shape_size(tv->get_shape());
    size_t size = element_count * sizeof(T);
    std::vector<T> rc(element_count);
    tv->read(rc.data(), 0, size);
    return rc;
}

std::vector<float> read_float_vector(std::shared_ptr<ngraph::runtime::Tensor> tv);

template <typename T>
void write_vector(std::shared_ptr<ngraph::runtime::Tensor> tv, const std::vector<T>& values)
{
    tv->write(values.data(), 0, values.size() * sizeof(T));
}

template <typename T>
std::vector<std::shared_ptr<T>> get_ops_of_type(std::shared_ptr<ngraph::Function> f)
{
    std::vector<std::shared_ptr<T>> ops;
    for (auto op : f->get_ops())
    {
        if (auto cop = std::dynamic_pointer_cast<T>(op))
        {
            ops.push_back(cop);
        }
    }

    return ops;
}

template <typename T>
size_t count_ops_of_type(std::shared_ptr<ngraph::Function> f)
{
    size_t count = 0;
    for (auto op : f->get_ops())
    {
        if (std::dynamic_pointer_cast<T>(op))
        {
            count++;
        }
    }

    return count;
}

template <typename T>
void init_int_tv(ngraph::runtime::Tensor* tv, std::default_random_engine& engine, T min, T max)
{
    size_t size = tv->get_element_count();
    std::uniform_int_distribution<T> dist(min, max);
    std::vector<T> vec(size);
    for (T& element : vec)
    {
        element = dist(engine);
    }
    tv->write(vec.data(), 0, vec.size() * sizeof(T));
}

template <typename T>
void init_real_tv(ngraph::runtime::Tensor* tv, std::default_random_engine& engine, T min, T max)
{
    size_t size = tv->get_element_count();
    std::uniform_real_distribution<T> dist(min, max);
    std::vector<T> vec(size);
    for (T& element : vec)
    {
        element = dist(engine);
    }
    tv->write(vec.data(), 0, vec.size() * sizeof(T));
}

void random_init(ngraph::runtime::Tensor* tv, std::default_random_engine& engine);

template <typename T>
std::vector<std::shared_ptr<ngraph::runtime::Tensor>>
    prepare_and_run(const std::shared_ptr<ngraph::Function>& function,
                    std::vector<std::vector<T>> args,
                    const std::string& backend_id)
{
    auto backend = ngraph::runtime::Backend::create(backend_id);

    auto parms = function->get_parameters();

    if (parms.size() != args.size())
    {
        throw ngraph::ngraph_error("number of parameters and arguments don't match");
    }

    std::vector<std::shared_ptr<ngraph::runtime::Tensor>> arg_tensors(args.size());
    for (size_t i = 0; i < args.size(); i++)
    {
        auto t = backend->create_tensor(parms.at(i)->get_element_type(), parms.at(i)->get_shape());
        copy_data(t, args.at(i));
        arg_tensors.at(i) = t;
    }

    auto results = function->get_results();
    std::vector<std::shared_ptr<ngraph::runtime::Tensor>> result_tensors(results.size());

    for (size_t i = 0; i < results.size(); i++)
    {
        result_tensors.at(i) =
            backend->create_tensor(results.at(i)->get_element_type(), results.at(i)->get_shape());
    }

    auto handle = backend->compile(function);
    backend->call_with_validate(handle, result_tensors, arg_tensors);
    return result_tensors;
}

template <typename T, typename T1 = T>
std::vector<std::vector<T1>> execute(const std::shared_ptr<ngraph::Function>& function,
                                     std::vector<std::vector<T>> args,
                                     const std::string& backend_id)
{
    std::vector<std::shared_ptr<ngraph::runtime::Tensor>> result_tensors =
        prepare_and_run(function, args, backend_id);

    std::vector<std::vector<T1>> result_vectors;
    for (auto rt : result_tensors)
    {
        result_vectors.push_back(read_vector<T1>(rt));
    }
    return result_vectors;
}

template <typename T>
std::string
    get_results_str(std::vector<T>& ref_data, std::vector<T>& actual_data, size_t max_results = 16)
{
    std::stringstream ss;
    size_t num_results = std::min(static_cast<size_t>(max_results), ref_data.size());
    ss << "First " << num_results << " results";
    for (size_t i = 0; i < num_results; ++i)
    {
        ss << "\n"
           << std::setw(4) << i << " ref: " << std::setw(16) << std::left << ref_data[i]
           << "  actual: " << std::setw(16) << std::left << actual_data[i];
    }
    ss << "\n";

    return ss.str();
}

template <>
std::string get_results_str(std::vector<char>& ref_data,
                            std::vector<char>& actual_data,
                            size_t max_results);
<commit_msg>Utility function for reading binary file content. (#2423)<commit_after>//*****************************************************************************
// Copyright 2017-2019 Intel Corporation
//
// 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.
//*****************************************************************************

#pragma once

#include <exception>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <list>
#include <memory>
#include <random>
#include <vector>

#include "ngraph/descriptor/layout/tensor_layout.hpp"
#include "ngraph/file_util.hpp"
#include "ngraph/log.hpp"
#include "ngraph/runtime/backend.hpp"
#include "ngraph/runtime/tensor.hpp"
#include "ngraph/serializer.hpp"

namespace ngraph
{
    class Node;
    class Function;
}

bool validate_list(const std::list<std::shared_ptr<ngraph::Node>>& nodes);
std::shared_ptr<ngraph::Function> make_test_graph();
std::shared_ptr<ngraph::Function> make_function_from_file(const std::string& file_name);

template <typename T>
void copy_data(std::shared_ptr<ngraph::runtime::Tensor> tv, const std::vector<T>& data)
{
    size_t data_size = data.size() * sizeof(T);
    tv->write(data.data(), 0, data_size);
}

template <typename T>
std::vector<T> read_vector(std::shared_ptr<ngraph::runtime::Tensor> tv)
{
    if (ngraph::element::from<T>() != tv->get_tensor_layout()->get_element_type())
    {
        throw std::invalid_argument("read_vector type must match Tensor type");
    }
    size_t element_count = ngraph::shape_size(tv->get_shape());
    size_t size = element_count * sizeof(T);
    std::vector<T> rc(element_count);
    tv->read(rc.data(), 0, size);
    return rc;
}

std::vector<float> read_float_vector(std::shared_ptr<ngraph::runtime::Tensor> tv);

template <typename T>
void write_vector(std::shared_ptr<ngraph::runtime::Tensor> tv, const std::vector<T>& values)
{
    tv->write(values.data(), 0, values.size() * sizeof(T));
}

template <typename T>
std::vector<std::shared_ptr<T>> get_ops_of_type(std::shared_ptr<ngraph::Function> f)
{
    std::vector<std::shared_ptr<T>> ops;
    for (auto op : f->get_ops())
    {
        if (auto cop = std::dynamic_pointer_cast<T>(op))
        {
            ops.push_back(cop);
        }
    }

    return ops;
}

template <typename T>
size_t count_ops_of_type(std::shared_ptr<ngraph::Function> f)
{
    size_t count = 0;
    for (auto op : f->get_ops())
    {
        if (std::dynamic_pointer_cast<T>(op))
        {
            count++;
        }
    }

    return count;
}

template <typename T>
void init_int_tv(ngraph::runtime::Tensor* tv, std::default_random_engine& engine, T min, T max)
{
    size_t size = tv->get_element_count();
    std::uniform_int_distribution<T> dist(min, max);
    std::vector<T> vec(size);
    for (T& element : vec)
    {
        element = dist(engine);
    }
    tv->write(vec.data(), 0, vec.size() * sizeof(T));
}

template <typename T>
void init_real_tv(ngraph::runtime::Tensor* tv, std::default_random_engine& engine, T min, T max)
{
    size_t size = tv->get_element_count();
    std::uniform_real_distribution<T> dist(min, max);
    std::vector<T> vec(size);
    for (T& element : vec)
    {
        element = dist(engine);
    }
    tv->write(vec.data(), 0, vec.size() * sizeof(T));
}

void random_init(ngraph::runtime::Tensor* tv, std::default_random_engine& engine);

template <typename T>
std::vector<std::shared_ptr<ngraph::runtime::Tensor>>
    prepare_and_run(const std::shared_ptr<ngraph::Function>& function,
                    std::vector<std::vector<T>> args,
                    const std::string& backend_id)
{
    auto backend = ngraph::runtime::Backend::create(backend_id);

    auto parms = function->get_parameters();

    if (parms.size() != args.size())
    {
        throw ngraph::ngraph_error("number of parameters and arguments don't match");
    }

    std::vector<std::shared_ptr<ngraph::runtime::Tensor>> arg_tensors(args.size());
    for (size_t i = 0; i < args.size(); i++)
    {
        auto t = backend->create_tensor(parms.at(i)->get_element_type(), parms.at(i)->get_shape());
        copy_data(t, args.at(i));
        arg_tensors.at(i) = t;
    }

    auto results = function->get_results();
    std::vector<std::shared_ptr<ngraph::runtime::Tensor>> result_tensors(results.size());

    for (size_t i = 0; i < results.size(); i++)
    {
        result_tensors.at(i) =
            backend->create_tensor(results.at(i)->get_element_type(), results.at(i)->get_shape());
    }

    auto handle = backend->compile(function);
    backend->call_with_validate(handle, result_tensors, arg_tensors);
    return result_tensors;
}

template <typename T, typename T1 = T>
std::vector<std::vector<T1>> execute(const std::shared_ptr<ngraph::Function>& function,
                                     std::vector<std::vector<T>> args,
                                     const std::string& backend_id)
{
    std::vector<std::shared_ptr<ngraph::runtime::Tensor>> result_tensors =
        prepare_and_run(function, args, backend_id);

    std::vector<std::vector<T1>> result_vectors;
    for (auto rt : result_tensors)
    {
        result_vectors.push_back(read_vector<T1>(rt));
    }
    return result_vectors;
}

template <typename T>
std::string
    get_results_str(std::vector<T>& ref_data, std::vector<T>& actual_data, size_t max_results = 16)
{
    std::stringstream ss;
    size_t num_results = std::min(static_cast<size_t>(max_results), ref_data.size());
    ss << "First " << num_results << " results";
    for (size_t i = 0; i < num_results; ++i)
    {
        ss << "\n"
           << std::setw(4) << i << " ref: " << std::setw(16) << std::left << ref_data[i]
           << "  actual: " << std::setw(16) << std::left << actual_data[i];
    }
    ss << "\n";

    return ss.str();
}

template <>
std::string get_results_str(std::vector<char>& ref_data,
                            std::vector<char>& actual_data,
                            size_t max_results);

/// \brief      Reads a binary file to a vector.
///
/// \param[in]  path  The path where the file is located.
///
/// \tparam     T     The type we want to interpret as the elements in binary file.
///
/// \return     Return vector of data read from input binary file.
///
template <typename T>
std::vector<T> read_binary_file(const std::string& path)
{
    std::vector<T> file_content;
    std::ifstream inputs_fs{path, std::ios::in | std::ios::binary};
    if (!inputs_fs)
    {
        throw std::runtime_error("Failed to open the file: " + path);
    }

    inputs_fs.seekg(0, std::ios::end);
    auto size = inputs_fs.tellg();
    inputs_fs.seekg(0, std::ios::beg);
    if (size % sizeof(T) != 0)
    {
        throw std::runtime_error(
            "Error reading binary file content: Input file size (in bytes) "
            "is not a multiple of requested data type size.");
    }
    file_content.resize(size / sizeof(T));
    inputs_fs.read(reinterpret_cast<char*>(file_content.data()), size);
    return file_content;
}
<|endoftext|>


<commit_before>#include "connected_test.h"
#include <iostream>

using namespace AmqpClient;

TEST_F(connected_test, basic_consume)
{
  std::string queue = channel->DeclareQueue("");
  std::string consumer = channel->BasicConsume(queue);
}

TEST_F(connected_test, basic_consume_badqueue)
{
  EXPECT_THROW(channel->BasicConsume("test_consume_noexistqueue"), ChannelException);
}

TEST_F(connected_test, basic_consume_duplicatetag)
{
  std::string queue = channel->DeclareQueue("");
  std::string consumer = channel->BasicConsume(queue);
  EXPECT_THROW(channel->BasicConsume(queue, consumer), ChannelException);
}

TEST_F(connected_test, basic_cancel_consumer)
{
  std::string queue = channel->DeclareQueue("");
  std::string consumer = channel->BasicConsume(queue);
  channel->BasicCancel(consumer);
}

TEST_F(connected_test, basic_cancel_bad_consumer)
{
  EXPECT_THROW(channel->BasicCancel("test_consume_noexistconsumer"), ConsumerTagNotFoundException);
}

TEST_F(connected_test, basic_cancel_cancelled_consumer)
{
  std::string queue = channel->DeclareQueue("");
  std::string consumer = channel->BasicConsume(queue);
  channel->BasicCancel(consumer);
  EXPECT_THROW(channel->BasicCancel(consumer), ConsumerTagNotFoundException);
}

TEST_F(connected_test, basic_consume_message)
{
  BasicMessage::ptr_t message = BasicMessage::Create("Message Body");
  std::string queue = channel->DeclareQueue("");
  std::string consumer = channel->BasicConsume(queue);
  channel->BasicPublish("", queue, message);

  Envelope::ptr_t delivered;
  EXPECT_TRUE(channel->BasicConsumeMessage(consumer, delivered, -1));
  EXPECT_EQ(consumer, delivered->ConsumerTag());
  EXPECT_EQ("", delivered->Exchange());
  EXPECT_EQ(queue, delivered->RoutingKey());
  EXPECT_EQ(message->Body(), delivered->Message()->Body());
}

TEST_F(connected_test, basic_consume_message_bad_consumer)
{
  EXPECT_THROW(channel->BasicConsumeMessage("test_consume_noexistconsumer"), ConsumerTagNotFoundException);
}

TEST_F(connected_test, basic_consume_inital_qos)
{
  BasicMessage::ptr_t message1 = BasicMessage::Create("Message1");
  BasicMessage::ptr_t message2 = BasicMessage::Create("Message2");
  BasicMessage::ptr_t message3 = BasicMessage::Create("Message3");

  std::string queue = channel->DeclareQueue("");
  channel->BasicPublish("", queue, message1, true);
  channel->BasicPublish("", queue, message2, true);
  channel->BasicPublish("", queue, message3, true);

  std::string consumer = channel->BasicConsume(queue, "", true, false, true, 1);
  Envelope::ptr_t received1, received2;
  EXPECT_TRUE(channel->BasicConsumeMessage(consumer, received1, 1));

  EXPECT_FALSE(channel->BasicConsumeMessage(consumer, received2, 0));
  channel->BasicAck(received1);

  EXPECT_TRUE(channel->BasicConsumeMessage(consumer, received2, 1));
}

TEST_F(connected_test, basic_consume_2consumers)
{
  BasicMessage::ptr_t message1 = BasicMessage::Create("Message1");
  BasicMessage::ptr_t message2 = BasicMessage::Create("Message2");
  BasicMessage::ptr_t message3 = BasicMessage::Create("Message3");

  std::string queue1 = channel->DeclareQueue("");
  std::string queue2 = channel->DeclareQueue("");
  std::string queue3 = channel->DeclareQueue("");

  channel->BasicPublish("", queue1, message1);
  channel->BasicPublish("", queue2, message2);
  channel->BasicPublish("", queue3, message3);

  std::string consumer1 = channel->BasicConsume(queue1, "", true, false);
  std::string consumer2 = channel->BasicConsume(queue2, "", true, false);

  Envelope::ptr_t envelope1;
  Envelope::ptr_t envelope2;
  Envelope::ptr_t envelope3;

  channel->BasicConsumeMessage(consumer1, envelope1);
  channel->BasicAck(envelope1);
  channel->BasicConsumeMessage(consumer2, envelope2);
  channel->BasicAck(envelope2);
  channel->BasicGet(envelope3, queue3);
  channel->BasicAck(envelope3);
}

TEST_F(connected_test, basic_consume_1000messages)
{
  BasicMessage::ptr_t message1 = BasicMessage::Create("Message1");

  std::string queue = channel->DeclareQueue("");
  std::string consumer = channel->BasicConsume(queue, "");

  Envelope::ptr_t msg;
  for (int i = 0; i < 1000; ++i)
  {
    message1->Timestamp(i);
    channel->BasicPublish("", queue, message1, true);
    channel->BasicConsumeMessage(consumer, msg);
  }

}<commit_msg>Adding basic.qos and basic.recover test cases<commit_after>#include "connected_test.h"
#include <iostream>

using namespace AmqpClient;

TEST_F(connected_test, basic_consume)
{
  std::string queue = channel->DeclareQueue("");
  std::string consumer = channel->BasicConsume(queue);
}

TEST_F(connected_test, basic_consume_badqueue)
{
  EXPECT_THROW(channel->BasicConsume("test_consume_noexistqueue"), ChannelException);
}

TEST_F(connected_test, basic_consume_duplicatetag)
{
  std::string queue = channel->DeclareQueue("");
  std::string consumer = channel->BasicConsume(queue);
  EXPECT_THROW(channel->BasicConsume(queue, consumer), ChannelException);
}

TEST_F(connected_test, basic_cancel_consumer)
{
  std::string queue = channel->DeclareQueue("");
  std::string consumer = channel->BasicConsume(queue);
  channel->BasicCancel(consumer);
}

TEST_F(connected_test, basic_cancel_bad_consumer)
{
  EXPECT_THROW(channel->BasicCancel("test_consume_noexistconsumer"), ConsumerTagNotFoundException);
}

TEST_F(connected_test, basic_cancel_cancelled_consumer)
{
  std::string queue = channel->DeclareQueue("");
  std::string consumer = channel->BasicConsume(queue);
  channel->BasicCancel(consumer);
  EXPECT_THROW(channel->BasicCancel(consumer), ConsumerTagNotFoundException);
}

TEST_F(connected_test, basic_consume_message)
{
  BasicMessage::ptr_t message = BasicMessage::Create("Message Body");
  std::string queue = channel->DeclareQueue("");
  std::string consumer = channel->BasicConsume(queue);
  channel->BasicPublish("", queue, message);

  Envelope::ptr_t delivered;
  EXPECT_TRUE(channel->BasicConsumeMessage(consumer, delivered, -1));
  EXPECT_EQ(consumer, delivered->ConsumerTag());
  EXPECT_EQ("", delivered->Exchange());
  EXPECT_EQ(queue, delivered->RoutingKey());
  EXPECT_EQ(message->Body(), delivered->Message()->Body());
}

TEST_F(connected_test, basic_consume_message_bad_consumer)
{
  EXPECT_THROW(channel->BasicConsumeMessage("test_consume_noexistconsumer"), ConsumerTagNotFoundException);
}

TEST_F(connected_test, basic_consume_inital_qos)
{
  BasicMessage::ptr_t message1 = BasicMessage::Create("Message1");
  BasicMessage::ptr_t message2 = BasicMessage::Create("Message2");
  BasicMessage::ptr_t message3 = BasicMessage::Create("Message3");

  std::string queue = channel->DeclareQueue("");
  channel->BasicPublish("", queue, message1, true);
  channel->BasicPublish("", queue, message2, true);
  channel->BasicPublish("", queue, message3, true);

  std::string consumer = channel->BasicConsume(queue, "", true, false, true, 1);
  Envelope::ptr_t received1, received2;
  EXPECT_TRUE(channel->BasicConsumeMessage(consumer, received1, 1));

  EXPECT_FALSE(channel->BasicConsumeMessage(consumer, received2, 0));
  channel->BasicAck(received1);

  EXPECT_TRUE(channel->BasicConsumeMessage(consumer, received2, 1));
}

TEST_F(connected_test, basic_consume_2consumers)
{
  BasicMessage::ptr_t message1 = BasicMessage::Create("Message1");
  BasicMessage::ptr_t message2 = BasicMessage::Create("Message2");
  BasicMessage::ptr_t message3 = BasicMessage::Create("Message3");

  std::string queue1 = channel->DeclareQueue("");
  std::string queue2 = channel->DeclareQueue("");
  std::string queue3 = channel->DeclareQueue("");

  channel->BasicPublish("", queue1, message1);
  channel->BasicPublish("", queue2, message2);
  channel->BasicPublish("", queue3, message3);

  std::string consumer1 = channel->BasicConsume(queue1, "", true, false);
  std::string consumer2 = channel->BasicConsume(queue2, "", true, false);

  Envelope::ptr_t envelope1;
  Envelope::ptr_t envelope2;
  Envelope::ptr_t envelope3;

  channel->BasicConsumeMessage(consumer1, envelope1);
  channel->BasicAck(envelope1);
  channel->BasicConsumeMessage(consumer2, envelope2);
  channel->BasicAck(envelope2);
  channel->BasicGet(envelope3, queue3);
  channel->BasicAck(envelope3);
}

TEST_F(connected_test, basic_consume_1000messages)
{
  BasicMessage::ptr_t message1 = BasicMessage::Create("Message1");

  std::string queue = channel->DeclareQueue("");
  std::string consumer = channel->BasicConsume(queue, "");

  Envelope::ptr_t msg;
  for (int i = 0; i < 1000; ++i)
  {
    message1->Timestamp(i);
    channel->BasicPublish("", queue, message1, true);
    channel->BasicConsumeMessage(consumer, msg);
  }

}

TEST_F(connected_test, basic_recover)
{
  BasicMessage::ptr_t message = BasicMessage::Create("Message1");

  std::string queue = channel->DeclareQueue("");
  std::string consumer = channel->BasicConsume(queue, "", true, false);
  channel->BasicPublish("", queue, message);

  Envelope::ptr_t message1;
  Envelope::ptr_t message2;

  EXPECT_TRUE(channel->BasicConsumeMessage(consumer, message1));
  channel->BasicRecover(consumer);
  EXPECT_TRUE(channel->BasicConsumeMessage(consumer, message2));

  channel->DeleteQueue(queue);
}

TEST_F(connected_test, basic_recover_badconsumer)
{
  EXPECT_THROW(channel->BasicRecover("consumer_notexist"), ConsumerTagNotFoundException);
}

TEST_F(connected_test, basic_qos)
{
  std::string queue = channel->DeclareQueue("");
  std::string consumer = channel->BasicConsume(queue, "", true, false);
  channel->BasicPublish("", queue, BasicMessage::Create("Message1"));
  channel->BasicPublish("", queue, BasicMessage::Create("Message2"));

  Envelope::ptr_t incoming;
  EXPECT_TRUE(channel->BasicConsumeMessage(consumer, incoming, 1));
  EXPECT_FALSE(channel->BasicConsumeMessage(consumer, incoming, 1));

  channel->BasicQos(consumer, 2);
  EXPECT_TRUE(channel->BasicConsumeMessage(consumer, incoming, 1));

  channel->DeleteQueue(queue);
}

TEST_F(connected_test, basic_qos_badconsumer)
{
  EXPECT_THROW(channel->BasicQos("consumer_notexist", 1), ConsumerTagNotFoundException);
}<|endoftext|>


<commit_before>// Copyright 2015 PDFium 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 "testing/test_support.h"

#include <stdio.h>
#include <string.h>

#include <string>

#include "testing/utils/path_service.h"

#ifdef PDF_ENABLE_V8
#include "v8/include/libplatform/libplatform.h"
#endif

namespace {

#ifdef PDF_ENABLE_V8
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
// Returns the full path for an external V8 data file based on either
// the currect exectuable path or an explicit override.
std::string GetFullPathForSnapshotFile(const std::string& exe_path,
                                       const std::string& bin_dir,
                                       const std::string& filename) {
  std::string result;
  if (!bin_dir.empty()) {
    result = bin_dir;
    if (*bin_dir.rbegin() != PATH_SEPARATOR) {
      result += PATH_SEPARATOR;
    }
  } else if (!exe_path.empty()) {
    size_t last_separator = exe_path.rfind(PATH_SEPARATOR);
    if (last_separator != std::string::npos) {
      result = exe_path.substr(0, last_separator + 1);
    }
  }
  result += filename;
  return result;
}

bool GetExternalData(const std::string& exe_path,
                     const std::string& bin_dir,
                     const std::string& filename,
                     v8::StartupData* result_data) {
  std::string full_path =
      GetFullPathForSnapshotFile(exe_path, bin_dir, filename);
  size_t data_length = 0;
  std::unique_ptr<char, pdfium::FreeDeleter> data_buffer =
      GetFileContents(full_path.c_str(), &data_length);
  if (!data_buffer)
    return false;

  result_data->data = data_buffer.release();
  result_data->raw_size = data_length;
  return true;
}
#endif  // V8_USE_EXTERNAL_STARTUP_DATA

void InitializeV8Common(const char* exe_path, v8::Platform** platform) {
  v8::V8::InitializeICUDefaultLocation(exe_path);

  *platform = v8::platform::CreateDefaultPlatform();
  v8::V8::InitializePlatform(*platform);
  v8::V8::Initialize();

  // By enabling predictable mode, V8 won't post any background tasks.
  const char predictable_flag[] = "--predictable";
  v8::V8::SetFlagsFromString(predictable_flag,
                             static_cast<int>(strlen(predictable_flag)));
}
#endif  // PDF_ENABLE_V8

}  // namespace

std::unique_ptr<char, pdfium::FreeDeleter> GetFileContents(const char* filename,
                                                           size_t* retlen) {
  FILE* file = fopen(filename, "rb");
  if (!file) {
    fprintf(stderr, "Failed to open: %s\n", filename);
    return nullptr;
  }
  (void)fseek(file, 0, SEEK_END);
  size_t file_length = ftell(file);
  if (!file_length) {
    return nullptr;
  }
  (void)fseek(file, 0, SEEK_SET);
  std::unique_ptr<char, pdfium::FreeDeleter> buffer(
      static_cast<char*>(malloc(file_length)));
  if (!buffer) {
    return nullptr;
  }
  size_t bytes_read = fread(buffer.get(), 1, file_length, file);
  (void)fclose(file);
  if (bytes_read != file_length) {
    fprintf(stderr, "Failed to read: %s\n", filename);
    return nullptr;
  }
  *retlen = bytes_read;
  return buffer;
}

std::wstring GetPlatformWString(FPDF_WIDESTRING wstr) {
  if (!wstr)
    return nullptr;

  size_t characters = 0;
  while (wstr[characters])
    ++characters;

  std::wstring platform_string(characters, L'\0');
  for (size_t i = 0; i < characters + 1; ++i) {
    const unsigned char* ptr = reinterpret_cast<const unsigned char*>(&wstr[i]);
    platform_string[i] = ptr[0] + 256 * ptr[1];
  }
  return platform_string;
}

std::vector<std::string> StringSplit(const std::string& str, char delimiter) {
  std::vector<std::string> result;
  size_t pos = 0;
  while (1) {
    size_t found = str.find(delimiter, pos);
    if (found == std::string::npos)
      break;

    result.push_back(str.substr(pos, found - pos));
    pos = found + 1;
  }
  result.push_back(str.substr(pos));
  return result;
}

std::unique_ptr<unsigned short, pdfium::FreeDeleter> GetFPDFWideString(
    const std::wstring& wstr) {
  size_t length = sizeof(uint16_t) * (wstr.length() + 1);
  std::unique_ptr<unsigned short, pdfium::FreeDeleter> result(
      static_cast<unsigned short*>(malloc(length)));
  char* ptr = reinterpret_cast<char*>(result.get());
  size_t i = 0;
  for (wchar_t w : wstr) {
    ptr[i++] = w & 0xff;
    ptr[i++] = (w >> 8) & 0xff;
  }
  ptr[i++] = 0;
  ptr[i] = 0;
  return result;
}

#ifdef PDF_ENABLE_V8
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
bool InitializeV8ForPDFium(const std::string& exe_path,
                           const std::string& bin_dir,
                           v8::StartupData* natives_blob,
                           v8::StartupData* snapshot_blob,
                           v8::Platform** platform) {
  InitializeV8Common(exe_path.c_str(), platform);
  if (natives_blob && snapshot_blob) {
    if (!GetExternalData(exe_path, bin_dir, "natives_blob.bin", natives_blob))
      return false;
    if (!GetExternalData(exe_path, bin_dir, "snapshot_blob.bin", snapshot_blob))
      return false;
    v8::V8::SetNativesDataBlob(natives_blob);
    v8::V8::SetSnapshotDataBlob(snapshot_blob);
  }
  return true;
}
#else   // V8_USE_EXTERNAL_STARTUP_DATA
bool InitializeV8ForPDFium(const std::string& exe_path,
                           v8::Platform** platform) {
  InitializeV8Common(exe_path.c_str(), platform);
  return true;
}
#endif  // V8_USE_EXTERNAL_STARTUP_DATA
#endif  // PDF_ENABLE_V8

TestLoader::TestLoader(const char* pBuf, size_t len)
    : m_pBuf(pBuf), m_Len(len) {
}

// static
int TestLoader::GetBlock(void* param,
                         unsigned long pos,
                         unsigned char* pBuf,
                         unsigned long size) {
  TestLoader* pLoader = static_cast<TestLoader*>(param);
  if (pos + size < pos || pos + size > pLoader->m_Len)
    return 0;

  memcpy(pBuf, pLoader->m_pBuf + pos, size);
  return 1;
}

TestSaver::TestSaver() {
  FPDF_FILEWRITE::version = 1;
  FPDF_FILEWRITE::WriteBlock = WriteBlockCallback;
}

void TestSaver::ClearString() {
  m_String.clear();
}

// static
int TestSaver::WriteBlockCallback(FPDF_FILEWRITE* pFileWrite,
                                  const void* data,
                                  unsigned long size) {
  TestSaver* pThis = static_cast<TestSaver*>(pFileWrite);
  pThis->m_String.append(static_cast<const char*>(data), size);
  return 1;
}
<commit_msg>Pass expose-gc flag to pdfium test programs.<commit_after>// Copyright 2015 PDFium 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 "testing/test_support.h"

#include <stdio.h>
#include <string.h>

#include <string>

#include "testing/utils/path_service.h"

#ifdef PDF_ENABLE_V8
#include "v8/include/libplatform/libplatform.h"
#endif

namespace {

#ifdef PDF_ENABLE_V8
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
// Returns the full path for an external V8 data file based on either
// the currect exectuable path or an explicit override.
std::string GetFullPathForSnapshotFile(const std::string& exe_path,
                                       const std::string& bin_dir,
                                       const std::string& filename) {
  std::string result;
  if (!bin_dir.empty()) {
    result = bin_dir;
    if (*bin_dir.rbegin() != PATH_SEPARATOR) {
      result += PATH_SEPARATOR;
    }
  } else if (!exe_path.empty()) {
    size_t last_separator = exe_path.rfind(PATH_SEPARATOR);
    if (last_separator != std::string::npos) {
      result = exe_path.substr(0, last_separator + 1);
    }
  }
  result += filename;
  return result;
}

bool GetExternalData(const std::string& exe_path,
                     const std::string& bin_dir,
                     const std::string& filename,
                     v8::StartupData* result_data) {
  std::string full_path =
      GetFullPathForSnapshotFile(exe_path, bin_dir, filename);
  size_t data_length = 0;
  std::unique_ptr<char, pdfium::FreeDeleter> data_buffer =
      GetFileContents(full_path.c_str(), &data_length);
  if (!data_buffer)
    return false;

  result_data->data = data_buffer.release();
  result_data->raw_size = data_length;
  return true;
}
#endif  // V8_USE_EXTERNAL_STARTUP_DATA

void InitializeV8Common(const char* exe_path, v8::Platform** platform) {
  v8::V8::InitializeICUDefaultLocation(exe_path);

  *platform = v8::platform::CreateDefaultPlatform();
  v8::V8::InitializePlatform(*platform);

  // By enabling predictable mode, V8 won't post any background tasks.
  // By enabling GC, it makes it easier to chase use-after-free.
  const char v8_flags[] = "--predictable --expose-gc";
  v8::V8::SetFlagsFromString(v8_flags, static_cast<int>(strlen(v8_flags)));
  v8::V8::Initialize();
}
#endif  // PDF_ENABLE_V8

}  // namespace

std::unique_ptr<char, pdfium::FreeDeleter> GetFileContents(const char* filename,
                                                           size_t* retlen) {
  FILE* file = fopen(filename, "rb");
  if (!file) {
    fprintf(stderr, "Failed to open: %s\n", filename);
    return nullptr;
  }
  (void)fseek(file, 0, SEEK_END);
  size_t file_length = ftell(file);
  if (!file_length) {
    return nullptr;
  }
  (void)fseek(file, 0, SEEK_SET);
  std::unique_ptr<char, pdfium::FreeDeleter> buffer(
      static_cast<char*>(malloc(file_length)));
  if (!buffer) {
    return nullptr;
  }
  size_t bytes_read = fread(buffer.get(), 1, file_length, file);
  (void)fclose(file);
  if (bytes_read != file_length) {
    fprintf(stderr, "Failed to read: %s\n", filename);
    return nullptr;
  }
  *retlen = bytes_read;
  return buffer;
}

std::wstring GetPlatformWString(FPDF_WIDESTRING wstr) {
  if (!wstr)
    return nullptr;

  size_t characters = 0;
  while (wstr[characters])
    ++characters;

  std::wstring platform_string(characters, L'\0');
  for (size_t i = 0; i < characters + 1; ++i) {
    const unsigned char* ptr = reinterpret_cast<const unsigned char*>(&wstr[i]);
    platform_string[i] = ptr[0] + 256 * ptr[1];
  }
  return platform_string;
}

std::vector<std::string> StringSplit(const std::string& str, char delimiter) {
  std::vector<std::string> result;
  size_t pos = 0;
  while (1) {
    size_t found = str.find(delimiter, pos);
    if (found == std::string::npos)
      break;

    result.push_back(str.substr(pos, found - pos));
    pos = found + 1;
  }
  result.push_back(str.substr(pos));
  return result;
}

std::unique_ptr<unsigned short, pdfium::FreeDeleter> GetFPDFWideString(
    const std::wstring& wstr) {
  size_t length = sizeof(uint16_t) * (wstr.length() + 1);
  std::unique_ptr<unsigned short, pdfium::FreeDeleter> result(
      static_cast<unsigned short*>(malloc(length)));
  char* ptr = reinterpret_cast<char*>(result.get());
  size_t i = 0;
  for (wchar_t w : wstr) {
    ptr[i++] = w & 0xff;
    ptr[i++] = (w >> 8) & 0xff;
  }
  ptr[i++] = 0;
  ptr[i] = 0;
  return result;
}

#ifdef PDF_ENABLE_V8
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
bool InitializeV8ForPDFium(const std::string& exe_path,
                           const std::string& bin_dir,
                           v8::StartupData* natives_blob,
                           v8::StartupData* snapshot_blob,
                           v8::Platform** platform) {
  InitializeV8Common(exe_path.c_str(), platform);
  if (natives_blob && snapshot_blob) {
    if (!GetExternalData(exe_path, bin_dir, "natives_blob.bin", natives_blob))
      return false;
    if (!GetExternalData(exe_path, bin_dir, "snapshot_blob.bin", snapshot_blob))
      return false;
    v8::V8::SetNativesDataBlob(natives_blob);
    v8::V8::SetSnapshotDataBlob(snapshot_blob);
  }
  return true;
}
#else   // V8_USE_EXTERNAL_STARTUP_DATA
bool InitializeV8ForPDFium(const std::string& exe_path,
                           v8::Platform** platform) {
  InitializeV8Common(exe_path.c_str(), platform);
  return true;
}
#endif  // V8_USE_EXTERNAL_STARTUP_DATA
#endif  // PDF_ENABLE_V8

TestLoader::TestLoader(const char* pBuf, size_t len)
    : m_pBuf(pBuf), m_Len(len) {
}

// static
int TestLoader::GetBlock(void* param,
                         unsigned long pos,
                         unsigned char* pBuf,
                         unsigned long size) {
  TestLoader* pLoader = static_cast<TestLoader*>(param);
  if (pos + size < pos || pos + size > pLoader->m_Len)
    return 0;

  memcpy(pBuf, pLoader->m_pBuf + pos, size);
  return 1;
}

TestSaver::TestSaver() {
  FPDF_FILEWRITE::version = 1;
  FPDF_FILEWRITE::WriteBlock = WriteBlockCallback;
}

void TestSaver::ClearString() {
  m_String.clear();
}

// static
int TestSaver::WriteBlockCallback(FPDF_FILEWRITE* pFileWrite,
                                  const void* data,
                                  unsigned long size) {
  TestSaver* pThis = static_cast<TestSaver*>(pFileWrite);
  pThis->m_String.append(static_cast<const char*>(data), size);
  return 1;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2020 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkCanvas.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTextBlob.h"
#include "src/core/SkSurfacePriv.h"
#include "tests/Test.h"
#include "tools/ToolUtils.h"

SkBitmap rasterize_blob(SkTextBlob* blob,
                        const SkPaint& paint,
                        GrRecordingContext* rContext,
                        const SkMatrix& matrix) {
    const SkImageInfo info =
            SkImageInfo::Make(500, 500, kN32_SkColorType, kPremul_SkAlphaType);
    auto surface = SkSurface::MakeRenderTarget(rContext, SkBudgeted::kNo, info);
    auto canvas = surface->getCanvas();
    canvas->drawColor(SK_ColorWHITE);
    canvas->concat(matrix);
    canvas->drawTextBlob(blob, 10, 250, paint);
    SkBitmap bitmap;
    bitmap.allocN32Pixels(500, 500);
    surface->readPixels(bitmap, 0, 0);
    return bitmap;
}

bool check_for_black(const SkBitmap& bm) {
    for (int y = 0; y < bm.height(); y++) {
        for (int x = 0; x < bm.width(); x++) {
            if (bm.getColor(x, y) == SK_ColorBLACK) {
                return true;
            }
        }
    }
    return false;
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrTextBlobScaleAnimation, reporter, ctxInfo) {
    auto tf = ToolUtils::create_portable_typeface("Mono", SkFontStyle());
    SkFont font{tf};
    font.setHinting(SkFontHinting::kNormal);
    font.setSize(12);
    font.setEdging(SkFont::Edging::kAntiAlias);
    font.setSubpixel(true);

    SkTextBlobBuilder builder;
    const auto& runBuffer = builder.allocRunPosH(font, 30, 0, nullptr);

    for (int i = 0; i < 30; i++) {
        runBuffer.glyphs[i] = static_cast<SkGlyphID>(i);
        runBuffer.pos[i] = SkIntToScalar(i);
    }
    auto blob = builder.make();

    auto dContext = ctxInfo.directContext();
    bool anyBlack = false;
    for (int n = -13; n < 5; n++) {
        SkMatrix m = SkMatrix::Scale(std::exp2(n), std::exp2(n));
        auto bm = rasterize_blob(blob.get(), SkPaint(), dContext, m);
        anyBlack |= check_for_black(bm);
    }
    REPORTER_ASSERT(reporter, anyBlack);
}
<commit_msg>test for extents of SkTextBlob drawing<commit_after>/*
 * Copyright 2020 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkCanvas.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTextBlob.h"
#include "src/core/SkSurfacePriv.h"
#include "tests/Test.h"
#include "tools/ToolUtils.h"

SkBitmap rasterize_blob(SkTextBlob* blob,
                        const SkPaint& paint,
                        GrRecordingContext* rContext,
                        const SkMatrix& matrix) {
    const SkImageInfo info =
            SkImageInfo::Make(500, 500, kN32_SkColorType, kPremul_SkAlphaType);
    auto surface = SkSurface::MakeRenderTarget(rContext, SkBudgeted::kNo, info);
    auto canvas = surface->getCanvas();
    canvas->drawColor(SK_ColorWHITE);
    canvas->concat(matrix);
    canvas->drawTextBlob(blob, 10, 250, paint);
    SkBitmap bitmap;
    bitmap.allocN32Pixels(500, 500);
    surface->readPixels(bitmap, 0, 0);
    return bitmap;
}

bool check_for_black(const SkBitmap& bm) {
    for (int y = 0; y < bm.height(); y++) {
        for (int x = 0; x < bm.width(); x++) {
            if (bm.getColor(x, y) == SK_ColorBLACK) {
                return true;
            }
        }
    }
    return false;
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrTextBlobScaleAnimation, reporter, ctxInfo) {
    auto tf = ToolUtils::create_portable_typeface("Mono", SkFontStyle());
    SkFont font{tf};
    font.setHinting(SkFontHinting::kNormal);
    font.setSize(12);
    font.setEdging(SkFont::Edging::kAntiAlias);
    font.setSubpixel(true);

    SkTextBlobBuilder builder;
    const auto& runBuffer = builder.allocRunPosH(font, 30, 0, nullptr);

    for (int i = 0; i < 30; i++) {
        runBuffer.glyphs[i] = static_cast<SkGlyphID>(i);
        runBuffer.pos[i] = SkIntToScalar(i);
    }
    auto blob = builder.make();

    auto dContext = ctxInfo.directContext();
    bool anyBlack = false;
    for (int n = -13; n < 5; n++) {
        SkMatrix m = SkMatrix::Scale(std::exp2(n), std::exp2(n));
        auto bm = rasterize_blob(blob.get(), SkPaint(), dContext, m);
        anyBlack |= check_for_black(bm);
    }
    REPORTER_ASSERT(reporter, anyBlack);
}

// Test extreme positions for all combinations of positions, origins, and translation matrices.
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrTextBlobMoveAround, reporter, ctxInfo) {
    auto tf = ToolUtils::create_portable_typeface("Mono", SkFontStyle());
    SkFont font{tf};
    font.setHinting(SkFontHinting::kNormal);
    font.setSize(12);
    font.setEdging(SkFont::Edging::kAntiAlias);
    font.setSubpixel(true);

    auto makeBlob = [&](SkPoint delta) {
        SkTextBlobBuilder builder;
        const auto& runBuffer = builder.allocRunPos(font, 30, nullptr);

        for (int i = 0; i < 30; i++) {
            runBuffer.glyphs[i] = static_cast<SkGlyphID>(i);
            runBuffer.points()[i] = SkPoint::Make(SkIntToScalar(i*10) + delta.x(), 50 + delta.y());
        }
        return builder.make();
    };

    auto dContext = ctxInfo.directContext();
    auto rasterizeBlob = [&](SkTextBlob* blob, SkPoint origin, const SkMatrix& matrix) {
        SkPaint paint;
        const SkImageInfo info =
                SkImageInfo::Make(350, 80, kN32_SkColorType, kPremul_SkAlphaType);
        auto surface = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kNo, info);
        auto canvas = surface->getCanvas();
        canvas->drawColor(SK_ColorWHITE);
        canvas->concat(matrix);
        canvas->drawTextBlob(blob, 10 + origin.x(), 40 + origin.y(), paint);
        SkBitmap bitmap;
        bitmap.allocN32Pixels(350, 80);
        surface->readPixels(bitmap, 0, 0);
        return bitmap;
    };

    SkBitmap benchMark;
    {
        auto blob = makeBlob({0, 0});
        benchMark = rasterizeBlob(blob.get(), {0,0}, SkMatrix::I());
    }

    auto checkBitmap = [&](const SkBitmap& bitmap) {
        REPORTER_ASSERT(reporter, benchMark.width() == bitmap.width());
        REPORTER_ASSERT(reporter, benchMark.width() == bitmap.width());

        for (int y = 0; y < benchMark.height(); y++) {
            for (int x = 0; x < benchMark.width(); x++) {
                if (benchMark.getColor(x, y) != bitmap.getColor(x, y)) {
                    return false;
                }
            }
        }
        return true;
    };

    SkScalar interestingNumbers[] = {-10'000'000, -1'000'000, -1, 0, +1, +1'000'000, +10'000'000};
    for (auto originX : interestingNumbers) {
        for (auto originY : interestingNumbers) {
            for (auto translateX : interestingNumbers) {
                for (auto translateY : interestingNumbers) {
                    // Make sure everything adds to zero.
                    SkScalar deltaPosX = -(originX + translateX);
                    SkScalar deltaPosY = -(originY + translateY);
                    auto blob = makeBlob({deltaPosX, deltaPosY});
                    SkMatrix t = SkMatrix::Translate(translateX, translateY);
                    auto bitmap = rasterizeBlob(blob.get(), {originX, originY}, t);
                    REPORTER_ASSERT(reporter, checkBitmap(bitmap));
                }
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>fix for root 6.24<commit_after><|endoftext|>


<commit_before>/***********************************************************************
 *    filename:   InputInjection.cpp
 *    created:    21/5/2013
 *    author:     Timotei Dolean
 *************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2013 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/

#include <boost/test/unit_test.hpp>

#include <vector>
#include <iostream>

#include "CEGUI/CEGUI.h"

using namespace CEGUI;

struct InputInjectionFixture
{
    InputInjectionFixture()
        : d_buttonHandledCount(0)
        , d_windowHandledCount(0)
    {
        System::getSingleton().notifyDisplaySizeChanged(Sizef(100, 100));
        Rectf constraint_area(0, 0, 100, 100);
        System::getSingleton().getDefaultGUIContext().getMouseCursor().setConstraintArea(&constraint_area);

        d_window = WindowManager::getSingleton().createWindow("DefaultWindow");
        d_window->setPosition(UVector2(cegui_reldim(0.0f), cegui_reldim(0.0f)));
        d_window->setSize(USize(cegui_reldim(1.0f), cegui_reldim(1.0f)));

        d_button = WindowManager::getSingleton().createWindow("CEGUI/PushButton");
        d_button->setPosition(UVector2(cegui_reldim(0.2f), cegui_reldim(0.2f)));
        d_button->setSize(USize(cegui_reldim(0.2f), cegui_reldim(0.2f)));

        d_editbox = WindowManager::getSingleton().createWindow("TaharezLook/Editbox");
        d_editbox->setPosition(UVector2(cegui_reldim(0.9f), cegui_reldim(0.9f)));
        d_editbox->setSize(USize(cegui_reldim(0.1f), cegui_reldim(0.1f)));

        d_window->addChild(d_editbox);
        d_window->addChild(d_button);

        System::getSingleton().getDefaultGUIContext().setRootWindow(d_window);

        d_windowConnections.push_back(
            d_window->subscribeEvent(Window::EventMouseClick,
                Event::Subscriber(&InputInjectionFixture::handleWindowEvent, this))
            );
        d_buttonConnections.push_back(
            d_button->subscribeEvent(PushButton::EventClicked,
                Event::Subscriber(&InputInjectionFixture::handleButtonEvent, this))
            );
    }

    ~InputInjectionFixture()
    {
        disconnectConnections(d_windowConnections);
        disconnectConnections(d_buttonConnections);

        System::getSingleton().getDefaultGUIContext().setRootWindow(0);

        WindowManager::getSingleton().destroyWindow(d_window);
    }

    bool handleButtonEvent(const EventArgs& e)
    {
        ++d_buttonHandledCount;
        return true;
    }

    bool handleWindowEvent(const EventArgs& e)
    {
        ++d_windowHandledCount;
        return true;
    }

    void disconnectConnections(std::vector<Event::Connection>& connections)
    {
        for(std::vector<Event::Connection>::iterator itor = connections.begin();
            itor != connections.end(); ++itor)
        {
            (*itor)->disconnect();
        }
    }

    int d_buttonHandledCount;
    int d_windowHandledCount;

    Window* d_window;
    Window* d_button;
    Window* d_editbox;

    std::vector<Event::Connection> d_windowConnections;
    std::vector<Event::Connection> d_buttonConnections;
};

//----------------------------------------------------------------------------//
static inline GUIContext& getGUIContext()
{
    return System::getSingleton().getDefaultGUIContext();
}

static void doClick(float position_x, float position_y)
{
    getGUIContext().injectMousePosition(position_x, position_y);
    getGUIContext().injectMouseButtonDown(LeftButton);
    getGUIContext().injectMouseButtonUp(LeftButton);
}
//----------------------------------------------------------------------------//

BOOST_FIXTURE_TEST_SUITE(InputInjection, InputInjectionFixture)

BOOST_AUTO_TEST_CASE(OneClickOnWindow)
{
    // we check for both: a) being handled, b) have the expected final result
    BOOST_REQUIRE_EQUAL(getGUIContext().injectMouseButtonClick(LeftButton), true);

    BOOST_REQUIRE_EQUAL(d_windowHandledCount, 1);
    BOOST_REQUIRE_EQUAL(d_buttonHandledCount, 0);
}

BOOST_AUTO_TEST_CASE(MultipleClicksOnWindow)
{
    BOOST_REQUIRE_EQUAL(getGUIContext().injectMouseButtonClick(LeftButton), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectMouseButtonClick(LeftButton), true);

    BOOST_REQUIRE_EQUAL(d_windowHandledCount, 2);
    BOOST_REQUIRE_EQUAL(d_buttonHandledCount, 0);
}

BOOST_AUTO_TEST_CASE(OneClickOnButton)
{
    doClick(30.0f, 30.0f);

    BOOST_REQUIRE_EQUAL(d_windowHandledCount, 0);
    BOOST_REQUIRE_EQUAL(d_buttonHandledCount, 1);
}

BOOST_AUTO_TEST_CASE(InsertSimpleText)
{
    // focus the editbox
    doClick(91.0f, 91.0f);

    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('W'), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('o'), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('W'), true);

    BOOST_REQUIRE_EQUAL(d_editbox->getText(), "WoW");
}

BOOST_AUTO_TEST_CASE(DeleteTextWithBackspace)
{
    // focus the editbox
    doClick(91.0f, 91.0f);

    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('W'), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('o'), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('k'), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectKeyDown(Key::Backspace), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('W'), true);

    BOOST_REQUIRE_EQUAL(d_editbox->getText(), "WoW");
}

BOOST_AUTO_TEST_CASE(DeleteTextWithDelete)
{
    // focus the editbox
    doClick(91.0f, 91.0f);

    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('W'), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('o'), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('k'), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('W'), true);

    BOOST_REQUIRE_EQUAL(getGUIContext().injectKeyDown(Key::ArrowLeft), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectKeyDown(Key::ArrowLeft), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectKeyDown(Key::Delete), true);

    BOOST_REQUIRE_EQUAL(d_editbox->getText(), "WoW");
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Fix the line ending for 'InputInjection' tests<commit_after>/***********************************************************************
 *    filename:   InputInjection.cpp
 *    created:    21/5/2013
 *    author:     Timotei Dolean
 *************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2013 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/

#include <boost/test/unit_test.hpp>

#include <vector>
#include <iostream>

#include "CEGUI/CEGUI.h"

using namespace CEGUI;

struct InputInjectionFixture
{
    InputInjectionFixture()
        : d_buttonHandledCount(0)
        , d_windowHandledCount(0)
    {
        System::getSingleton().notifyDisplaySizeChanged(Sizef(100, 100));
        Rectf constraint_area(0, 0, 100, 100);
        System::getSingleton().getDefaultGUIContext().getMouseCursor().setConstraintArea(&constraint_area);

        d_window = WindowManager::getSingleton().createWindow("DefaultWindow");
        d_window->setPosition(UVector2(cegui_reldim(0.0f), cegui_reldim(0.0f)));
        d_window->setSize(USize(cegui_reldim(1.0f), cegui_reldim(1.0f)));

        d_button = WindowManager::getSingleton().createWindow("CEGUI/PushButton");
        d_button->setPosition(UVector2(cegui_reldim(0.2f), cegui_reldim(0.2f)));
        d_button->setSize(USize(cegui_reldim(0.2f), cegui_reldim(0.2f)));

        d_editbox = WindowManager::getSingleton().createWindow("TaharezLook/Editbox");
        d_editbox->setPosition(UVector2(cegui_reldim(0.9f), cegui_reldim(0.9f)));
        d_editbox->setSize(USize(cegui_reldim(0.1f), cegui_reldim(0.1f)));

        d_window->addChild(d_editbox);
        d_window->addChild(d_button);

        System::getSingleton().getDefaultGUIContext().setRootWindow(d_window);

        d_windowConnections.push_back(
            d_window->subscribeEvent(Window::EventMouseClick,
                Event::Subscriber(&InputInjectionFixture::handleWindowEvent, this))
            );
        d_buttonConnections.push_back(
            d_button->subscribeEvent(PushButton::EventClicked,
                Event::Subscriber(&InputInjectionFixture::handleButtonEvent, this))
            );
    }

    ~InputInjectionFixture()
    {
        disconnectConnections(d_windowConnections);
        disconnectConnections(d_buttonConnections);

        System::getSingleton().getDefaultGUIContext().setRootWindow(0);

        WindowManager::getSingleton().destroyWindow(d_window);
    }

    bool handleButtonEvent(const EventArgs& e)
    {
        ++d_buttonHandledCount;
        return true;
    }

    bool handleWindowEvent(const EventArgs& e)
    {
        ++d_windowHandledCount;
        return true;
    }

    void disconnectConnections(std::vector<Event::Connection>& connections)
    {
        for(std::vector<Event::Connection>::iterator itor = connections.begin();
            itor != connections.end(); ++itor)
        {
            (*itor)->disconnect();
        }
    }

    int d_buttonHandledCount;
    int d_windowHandledCount;

    Window* d_window;
    Window* d_button;
    Window* d_editbox;

    std::vector<Event::Connection> d_windowConnections;
    std::vector<Event::Connection> d_buttonConnections;
};

//----------------------------------------------------------------------------//
static inline GUIContext& getGUIContext()
{
    return System::getSingleton().getDefaultGUIContext();
}

static void doClick(float position_x, float position_y)
{
    getGUIContext().injectMousePosition(position_x, position_y);
    getGUIContext().injectMouseButtonDown(LeftButton);
    getGUIContext().injectMouseButtonUp(LeftButton);
}
//----------------------------------------------------------------------------//

BOOST_FIXTURE_TEST_SUITE(InputInjection, InputInjectionFixture)

BOOST_AUTO_TEST_CASE(OneClickOnWindow)
{
    // we check for both: a) being handled, b) have the expected final result
    BOOST_REQUIRE_EQUAL(getGUIContext().injectMouseButtonClick(LeftButton), true);

    BOOST_REQUIRE_EQUAL(d_windowHandledCount, 1);
    BOOST_REQUIRE_EQUAL(d_buttonHandledCount, 0);
}

BOOST_AUTO_TEST_CASE(MultipleClicksOnWindow)
{
    BOOST_REQUIRE_EQUAL(getGUIContext().injectMouseButtonClick(LeftButton), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectMouseButtonClick(LeftButton), true);

    BOOST_REQUIRE_EQUAL(d_windowHandledCount, 2);
    BOOST_REQUIRE_EQUAL(d_buttonHandledCount, 0);
}

BOOST_AUTO_TEST_CASE(OneClickOnButton)
{
    doClick(30.0f, 30.0f);

    BOOST_REQUIRE_EQUAL(d_windowHandledCount, 0);
    BOOST_REQUIRE_EQUAL(d_buttonHandledCount, 1);
}

BOOST_AUTO_TEST_CASE(InsertSimpleText)
{
    // focus the editbox
    doClick(91.0f, 91.0f);

    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('W'), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('o'), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('W'), true);

    BOOST_REQUIRE_EQUAL(d_editbox->getText(), "WoW");
}

BOOST_AUTO_TEST_CASE(DeleteTextWithBackspace)
{
    // focus the editbox
    doClick(91.0f, 91.0f);

    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('W'), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('o'), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('k'), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectKeyDown(Key::Backspace), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('W'), true);

    BOOST_REQUIRE_EQUAL(d_editbox->getText(), "WoW");
}

BOOST_AUTO_TEST_CASE(DeleteTextWithDelete)
{
    // focus the editbox
    doClick(91.0f, 91.0f);

    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('W'), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('o'), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('k'), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectChar('W'), true);

    BOOST_REQUIRE_EQUAL(getGUIContext().injectKeyDown(Key::ArrowLeft), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectKeyDown(Key::ArrowLeft), true);
    BOOST_REQUIRE_EQUAL(getGUIContext().injectKeyDown(Key::Delete), true);

    BOOST_REQUIRE_EQUAL(d_editbox->getText(), "WoW");
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#include "config_manager.h"

using namespace std;
using namespace TOOLS;

ConfigDataKeeper::ConfigDataKeeper(const ConfigDataKeeper& obj)
  : storage(obj.storage), tinfo(obj.tinfo) { }

ConfigDataKeeper::ConfigDataKeeper(void* data, const string& tinfo)
  : storage(data), tinfo(tinfo) { }

ConfigDataKeeper::ConfigDataKeeper(const string& tinfo)
  : storage(nullptr), tinfo(tinfo) { }

// return verbose type string
string ConfigDataKeeper::verbose_type() const {
  if(tinfo == typeid(int).name())
    return "integer";
  else if(tinfo == typeid(double).name())
    return "float";
  else if(tinfo == typeid(string).name())
    return "string";
  else if(tinfo == typeid(tStringList).name())
    return "string list";
  else if(tinfo == typeid(tStringMap).name())
    return "string map";
  else if(tinfo == typeid(bool).name())
    return "boolean";
  return "unknown data type!!! ";
}

// return verbose data string representation
string ConfigDataKeeper::verbose_data(void* raw_data) const {
  string out;
  const ConfigDataKeeper* cdk;
  if(raw_data != nullptr)
    cdk = new ConfigDataKeeper(raw_data, tinfo);
  else
    cdk = this;

  if(tinfo == typeid(int).name())
    out = str(cdk->get<int>());
  else if(tinfo == typeid(double).name())
    out = str(cdk->get<double>());
  else if(tinfo == typeid(string).name())
    out = cdk->get<string>();
  else if(tinfo == typeid(tStringList).name())
    out = XString(",").join(cdk->get<tStringList>());
  else if(tinfo == typeid(tStringMap).name()) {
    tStringList tmp;
    for(auto& key_val : cdk->get<tStringMap>())
      tmp.push_back(key_val.first + "=" + key_val.second);
    out = XString(",").join(tmp);
  } else if(tinfo == typeid(bool).name())
    out = (cdk->get<bool>()) ? "true" : "false";
  else
    out = "unknown data";

  if(raw_data != nullptr)
    delete cdk;
  return out;
}

ConfigOption::ConfigOption(const std::string& id, const std::string& desc, \
  const std::string& tinfo, const std::string& scmd)
  : data(tinfo), default_data(tinfo), id(id), cmd_short(scmd), desc(desc),
    was_set(false), has_default(false), parent(NULL) { }

string ConfigOption::verbose_type() const {
  return data.verbose_type();
}

string ConfigOption::verbose_data() const {
  return data.verbose_data();
}

string ConfigOption::verbose_default() const {
  if(has_default)
    return default_data.verbose_data();
  return "<no default set>";
}

ConfigGroup::ConfigGroup(const std::string& name, ConfigManager* par)
  : name(name), parent(par)  {}

ConfigGroup::iterator ConfigGroup::begin() {
  return members.begin();
}

ConfigGroup::const_iterator ConfigGroup::begin() const {
  return members.begin();
}

ConfigGroup::iterator ConfigGroup::end() {
  return members.end();
}

ConfigGroup::const_iterator ConfigGroup::end() const {
  return members.end();
}

ConfigOption& ConfigGroup::get_option(const std::string& id) {
  tOptionIter it = members.find(id);
  if(it != members.end())
    return *it->second;
  throw OptionNotFound(id);
}

ConfigGroup& ConfigManager::new_group(const std::string& name) {
  groups[name] = new ConfigGroup(name, this);
  return *groups[name];
}

ConfigGroup& ConfigManager::get_group(const string& name) {
  tGroupIter it = groups.find(name);
  if(it == groups.end())
    throw GroupNotFound(name);
  return *it->second;
}

ConfigGroup& ConfigManager::get_group_from_option(const string& name) {
  return *(get_option(name).parent);
}

ConfigOption& ConfigManager::get_option(const std::string& id) {
  tOptionIter it = members.find(id);
  if(it == members.end())
    throw OptionNotFound(id);
  return *(it->second);
}

ConfigManager::iterator ConfigManager::begin() {
  return groups.begin();
}

ConfigManager::const_iterator ConfigManager::begin() const {
  return groups.begin();
}

ConfigManager::iterator ConfigManager::end() {
  return groups.end();
}

ConfigManager::const_iterator ConfigManager::end() const {
  return groups.end();
}

ConfigManager::ConfigManager(const std::string& start_command)
  : command(start_command) { }

void ConfigManager::parse(tStringList* args) {
  string cmd = args->at(0);

  if(cmdmap.find(cmd) == cmdmap.end())
    throw UnknownParameter(cmd);

  string id = cmdmap[cmd];
  ConfigDataKeeper* tmp = &members[id]->data;

  // catch boolean value as this doesn't need an arg
  if(tmp->same_data_types<bool>()) {
    if(members[id]->has_default)
      set<bool>(id, !get<bool>(id));
    else
      set<bool>(id, true);
    args->erase(args->begin());
    return;
  }

  if(args->size() < 2)
    throw MissingParameter(cmd + " - found no more args");

  string arg = args->at(1);

  // check for integer and double
  try {
    if(tmp->same_data_types<int>()) {
      set<int>(id, integer(arg));
      args->erase(args->begin(), args->begin()+2);
      return;
    } else if(tmp->same_data_types<double>()) {
      set<double>(id, real(arg));
      args->erase(args->begin(), args->begin()+2);
      return;
    }
  } catch(ConvertValueError e) {
    throw IncompatibleDataTypes("data: " + tmp->verbose_type() + " passed: " + arg);
  }

  // get string
  if(tmp->same_data_types<string>()) {
    set<string>(id, str(arg));
    args->erase(args->begin(), args->begin()+2);
    return;
  }

  // build tStringList from "," separated input
  if(tmp->same_data_types<tStringList>()) {
    set<tStringList>(id, XString(arg).split(","));
    args->erase(args->begin(), args->begin()+2);
    return;
    // build tStringMap from "," and "=" separated input
  }
  if(tmp->same_data_types<tStringMap>()) {
    tStringList tmp = XString(arg).split(",");
    tStringMap tmpmap;
    for(tStringIter i=tmp.begin(); i!=tmp.end(); ++i) {
      tStringList two = XString(*i).split("=");
      tmpmap[two[0]] = two[1];
    }
    set<tStringMap>(id, tmpmap);
    args->erase(args->begin(), args->begin()+2);
    return;
  }
  throw IncompatibleDataTypes("data: " + tmp->verbose_type() + " passed: " + arg);
}

void ConfigManager::parse_cmdline(int argc, char* argv[]) {
  tStringList args;
  for(int i=1; i<argc; ++i)
    args.push_back(argv[i]);

  while(args.size() > 0)
    parse(&args);
}

void ConfigManager::write_config_file(ostream& fd, bool shorter) {
  fd << endl;
  fd << "###" << endl;
  fd << "### config file for: " << command << endl;
  fd << "###" << endl;
  fd << endl;
  for(tGroupPair& grp : groups) {
    if(!shorter)
      fd << "####################################################" << endl;
    fd << "# [ " << grp.first << " ]" << endl;
    for(tOptionPair& opt : *grp.second) {
      const ConfigOption* c = opt.second;
      const string& id = opt.first;

      // write desc/help text
      if(!shorter) {
        fd << "# " << c->desc << " [" << c->verbose_type() << "]";
        // write if ConfigOption has default
        if(c->has_default)
          fd << " default: " << c->verbose_default();
        fd << endl;
      }

      // ConfigOption was set, output its value
      if(c->was_set) {
        fd << id << " = " << c->verbose_data() << endl;
      // ConfigOption was _not_ set, output commented out line and default
      } else if(c->has_default) {
          fd << "# " << id << " = " << c->verbose_default() << endl;
      // ConfigOption was neither set nor has a default value
      } else {
        if(!shorter)
          fd << "# " << id << " = " << "<not set>" << endl;
      }
      if(!shorter)
        fd << endl;
    }
  }
}

void ConfigManager::parse_config_file(const string& fn) {
  ifstream fd(fn.c_str(), ios::in);
  XString line;
  tStringList tokens;
  while(fd.good()) {
    getline(fd, line);
    line.strip().strip("\n");
    if(line.length() == 0)
      continue;

    if(line.startswith("#"))
      continue;

    if(line.find("=") == string::npos) {
      tokens.push_back("--" + line);
      continue;
    }

    tStringList lr = line.split("=");
    XString left(lr[0]), right(lr[1]);
    left.strip();
    right.strip();

    tokens.push_back("--" + left);
    tokens.push_back(right);
  }
  fd.close();

  try {
    while(tokens.size() > 0)
      parse(&tokens);
  } catch(IncompatibleDataTypes& e) {
    e.message += " (inside configfile)";
    throw e;
  }
}

bool ConfigManager::is_group_active(const std::string& name) {
  tOptionMap& opts = groups[name]->members;
  for(tOptionIter i=opts.begin(); i!=opts.end(); ++i)
    if(i->second->was_set)
      return true;
  return false;
}

bool ConfigManager::is_option_set(const std::string& id) {
  return (get_option(id).was_set || get_option(id).has_default);
}

void ConfigManager::usage(ostream& ss) {
  ss << "Usage: " << command << " <options>" << endl;
  ss << endl << "Options:" << endl;

  string::size_type id_len = 0, scmd_len = 0, desc_len = 0;
  for(tStringMapIter i=cmdmap.begin(); i!=cmdmap.end(); ++i) {
    ConfigOption* opt = members[i->second];
    if(i->first.find("--") != string::npos)
      id_len = max(opt->id.length(), id_len);
    else
      scmd_len = max(opt->cmd_short.length(), scmd_len);
    desc_len = max(opt->desc.length(), desc_len);
  }

  for(tGroupIter g=groups.begin(); g!=groups.end(); ++g) {
    ConfigGroup* grp = g->second;
    ss << endl << "--- Group: " << grp->name << endl;
    for(tOptionIter i=grp->members.begin(); i!=grp->members.end(); ++i) {
      ConfigOption* opt = grp->members[i->first];

      ss << right << setw(scmd_len+1) << ((opt->cmd_short.size() > 0) ? \
                                          ("-" + opt->cmd_short) : "") << " | " << flush;
      ss << left << setw(id_len+2) << ("--" + opt->id) << "   " << opt->desc;
      ss << " [" << opt->data.verbose_type() << "]";
      ss << endl;
    }
  }
  ss << endl;
}
<commit_msg>wohooo goood work at configparser<commit_after>#include "config_manager.h"

using namespace std;
using namespace TOOLS;

ConfigDataKeeper::ConfigDataKeeper(const ConfigDataKeeper& obj)
  : storage(obj.storage), tinfo(obj.tinfo) { }

ConfigDataKeeper::ConfigDataKeeper(void* data, const string& tinfo)
  : storage(data), tinfo(tinfo) { }

ConfigDataKeeper::ConfigDataKeeper(const string& tinfo)
  : storage(nullptr), tinfo(tinfo) { }

// return verbose type string
string ConfigDataKeeper::verbose_type() const {
  if(tinfo == typeid(int).name())
    return "integer";
  else if(tinfo == typeid(double).name())
    return "float";
  else if(tinfo == typeid(string).name())
    return "string";
  else if(tinfo == typeid(tStringList).name())
    return "string list";
  else if(tinfo == typeid(tStringMap).name())
    return "string map";
  else if(tinfo == typeid(bool).name())
    return "boolean";
  return "unknown data type!!! ";
}

// return verbose data string representation
string ConfigDataKeeper::verbose_data(void* raw_data) const {
  string out;
  const ConfigDataKeeper* cdk;
  if(raw_data != nullptr)
    cdk = new ConfigDataKeeper(raw_data, tinfo);
  else
    cdk = this;

  if(tinfo == typeid(int).name())
    out = str(cdk->get<int>());
  else if(tinfo == typeid(double).name())
    out = str(cdk->get<double>());
  else if(tinfo == typeid(string).name())
    out = cdk->get<string>();
  else if(tinfo == typeid(tStringList).name())
    out = XString(",").join(cdk->get<tStringList>());
  else if(tinfo == typeid(tStringMap).name()) {
    tStringList tmp;
    for(auto& key_val : cdk->get<tStringMap>())
      tmp.push_back(key_val.first + ":" + key_val.second);
    out = XString(",").join(tmp);
  } else if(tinfo == typeid(bool).name())
    out = (cdk->get<bool>()) ? "true" : "false";
  else
    out = "unknown data";

  if(raw_data != nullptr)
    delete cdk;
  return out;
}

ConfigOption::ConfigOption(const std::string& id, const std::string& desc, \
  const std::string& tinfo, const std::string& scmd)
  : data(tinfo), default_data(tinfo), id(id), cmd_short(scmd), desc(desc),
    was_set(false), has_default(false), parent(NULL) { }

string ConfigOption::verbose_type() const {
  return data.verbose_type();
}

string ConfigOption::verbose_data() const {
  return data.verbose_data();
}

string ConfigOption::verbose_default() const {
  if(has_default)
    return default_data.verbose_data();
  return "<no default set>";
}

ConfigGroup::ConfigGroup(const std::string& name, ConfigManager* par)
  : name(name), parent(par)  {}

ConfigGroup::iterator ConfigGroup::begin() {
  return members.begin();
}

ConfigGroup::const_iterator ConfigGroup::begin() const {
  return members.begin();
}

ConfigGroup::iterator ConfigGroup::end() {
  return members.end();
}

ConfigGroup::const_iterator ConfigGroup::end() const {
  return members.end();
}

ConfigOption& ConfigGroup::get_option(const std::string& id) {
  tOptionIter it = members.find(id);
  if(it != members.end())
    return *it->second;
  throw OptionNotFound(id);
}

ConfigGroup& ConfigManager::new_group(const std::string& name) {
  groups[name] = new ConfigGroup(name, this);
  return *groups[name];
}

ConfigGroup& ConfigManager::get_group(const string& name) {
  tGroupIter it = groups.find(name);
  if(it == groups.end())
    throw GroupNotFound(name);
  return *it->second;
}

ConfigGroup& ConfigManager::get_group_from_option(const string& name) {
  return *(get_option(name).parent);
}

ConfigOption& ConfigManager::get_option(const std::string& id) {
  tOptionIter it = members.find(id);
  if(it == members.end())
    throw OptionNotFound(id);
  return *(it->second);
}

ConfigManager::iterator ConfigManager::begin() {
  return groups.begin();
}

ConfigManager::const_iterator ConfigManager::begin() const {
  return groups.begin();
}

ConfigManager::iterator ConfigManager::end() {
  return groups.end();
}

ConfigManager::const_iterator ConfigManager::end() const {
  return groups.end();
}

ConfigManager::ConfigManager(const std::string& start_command)
  : command(start_command) { }

void ConfigManager::parse(tStringList* args) {
  string cmd = args->at(0);

  if(cmdmap.find(cmd) == cmdmap.end())
    throw UnknownParameter(cmd);

  string id = cmdmap[cmd];
  ConfigDataKeeper* tmp = &members[id]->data;

  // catch boolean value as this doesn't need an arg
  if(tmp->same_data_types<bool>()) {
    // even if possible, a arg for bools may be passed
    bool explicit_set = false;
    if(args->at(1) == "true") {
      explicit_set = true;
      set<bool>(id, true);
    } else if(args->at(1) == "false") {
      explicit_set = true;
      set<bool>(id, false);

    }
    if(explicit_set) {
      args->erase(args->begin(), args->begin()+2);
      return;
    }

    // if not passed, just toggle or set to true
    if(members[id]->has_default)
      set<bool>(id, !get<bool>(id));
    else
      set<bool>(id, true);
    args->erase(args->begin());
  }

  if(args->size() < 2)
    throw MissingParameter(cmd + " - found no more args");

  string arg = args->at(1);

  // check for integer and double
  try {
    if(tmp->same_data_types<int>()) {
      set<int>(id, integer(arg));
      args->erase(args->begin(), args->begin()+2);
      return;
    } else if(tmp->same_data_types<double>()) {
      set<double>(id, real(arg));
      args->erase(args->begin(), args->begin()+2);
      return;
    }
  } catch(ConvertValueError e) {
    throw IncompatibleDataTypes("data: " + tmp->verbose_type() + " passed: " + arg);
  }

  // get string
  if(tmp->same_data_types<string>()) {
    set<string>(id, str(arg));
    args->erase(args->begin(), args->begin()+2);
    return;
  }

  // build tStringList from "," separated input
  if(tmp->same_data_types<tStringList>()) {
    set<tStringList>(id, XString(arg).split(","));
    args->erase(args->begin(), args->begin()+2);
    return;
    // build tStringMap from "," and ":" separated input
  }
  if(tmp->same_data_types<tStringMap>()) {
    tStringList tmp = XString(arg).split(",");
    tStringMap tmpmap;
    for(tStringIter i=tmp.begin(); i!=tmp.end(); ++i) {
      tStringList two = XString(*i).split(":");
      tmpmap[two[0]] = two[1];
    }
    set<tStringMap>(id, tmpmap);
    args->erase(args->begin(), args->begin()+2);
    return;
  }
  throw IncompatibleDataTypes("data: " + tmp->verbose_type() + " passed: " + arg);
}

void ConfigManager::parse_cmdline(int argc, char* argv[]) {
  tStringList args;
  for(int i=1; i<argc; ++i)
    args.push_back(argv[i]);

  while(args.size() > 0)
    parse(&args);
}

void ConfigManager::write_config_file(ostream& fd, bool shorter) {
  fd << endl;
  fd << "###" << endl;
  fd << "### config file for: " << command << endl;
  fd << "###" << endl;
  fd << endl;
  for(tGroupPair& grp : groups) {
    if(!shorter)
      fd << "####################################################" << endl;
    else
      fd << endl;
    fd << "# [ " << grp.first << " ]" << endl;
    for(tOptionPair& opt : *grp.second) {
      const ConfigOption* c = opt.second;
      const string& id = opt.first;

      // write desc/help text
      if(!shorter) {
        fd << "# " << c->desc << " [" << c->verbose_type() << "]";
        // write if ConfigOption has default
        if(c->has_default)
          fd << " default: " << c->verbose_default();
        fd << endl;
      }

      // ConfigOption was set, output its value
      if(c->was_set) {
        fd << id << " = " << c->verbose_data() << endl;
      // ConfigOption was _not_ set, output commented out line and default
      } else if(c->has_default) {
          fd << "# " << id << " = " << c->verbose_default() << endl;
      // ConfigOption was neither set nor has a default value
      } else {
        if(!shorter)
          fd << "# " << id << " = " << "<not set>" << endl;
      }
      if(!shorter)
        fd << endl;
    }
  }
}

void ConfigManager::parse_config_file(const string& fn) {
  ifstream fd(fn.c_str(), ios::in);
  XString line;
  tStringList tokens;
  while(fd.good()) {
    getline(fd, line);
    line.strip().strip("\n");
    if(line.length() == 0)
      continue;

    if(line.startswith("#"))
      continue;

    if(line.find("=") == string::npos) {
      tokens.push_back("--" + line);
      continue;
    }

    tStringList lr = line.split("=");
    XString left(lr[0]), right(lr[1]);
    left.strip();
    right.strip();

    tokens.push_back("--" + left);
    tokens.push_back(right);
  }
  fd.close();

  try {
    while(tokens.size() > 0)
      parse(&tokens);

  } catch(IncompatibleDataTypes& e) {
    e.message += " (inside configfile)";
    throw e;
  }
}

bool ConfigManager::is_group_active(const std::string& name) {
  tOptionMap& opts = groups[name]->members;
  for(tOptionIter i=opts.begin(); i!=opts.end(); ++i)
    if(i->second->was_set)
      return true;
  return false;
}

bool ConfigManager::is_option_set(const std::string& id) {
  return (get_option(id).was_set || get_option(id).has_default);
}

void ConfigManager::usage(ostream& ss) {
  ss << "Usage: " << command << " <options>" << endl;
  ss << endl << "Options:" << endl;

  string::size_type id_len = 0, scmd_len = 0, desc_len = 0;
  for(tStringMapIter i=cmdmap.begin(); i!=cmdmap.end(); ++i) {
    ConfigOption* opt = members[i->second];
    if(i->first.find("--") != string::npos)
      id_len = max(opt->id.length(), id_len);
    else
      scmd_len = max(opt->cmd_short.length(), scmd_len);
    desc_len = max(opt->desc.length(), desc_len);
  }

  for(tGroupIter g=groups.begin(); g!=groups.end(); ++g) {
    ConfigGroup* grp = g->second;
    ss << endl << "--- Group: " << grp->name << endl;
    for(tOptionIter i=grp->members.begin(); i!=grp->members.end(); ++i) {
      ConfigOption* opt = grp->members[i->first];

      ss << right << setw(scmd_len+1) << ((opt->cmd_short.size() > 0) ? \
                                          ("-" + opt->cmd_short) : "") << " | " << flush;
      ss << left << setw(id_len+2) << ("--" + opt->id) << "   " << opt->desc;
      ss << " [" << opt->data.verbose_type() << "]";
      ss << endl;
    }
  }
  ss << endl;
}
<|endoftext|>