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

#include <cstdint>
#include <iostream>
#include <string>

#include <caf/config_option_adder.hpp>

#include <broker/bro.hh>
#include <broker/broker.hh>

#include <vast/defaults.hpp>
#include <vast/error.hpp>
#include <vast/event.hpp>
#include <vast/expression.hpp>
#include <vast/uuid.hpp>

#include <vast/concept/parseable/parse.hpp>
#include <vast/concept/parseable/vast/expression.hpp>
#include <vast/concept/parseable/vast/uuid.hpp>

#include <vast/system/writer_command_base.hpp>
#include <vast/system/sink.hpp>

#include <vast/detail/add_message_types.hpp>
#include <vast/detail/assert.hpp>
#include <vast/detail/overload.hpp>

namespace {

constexpr char control_topic[] = "/vast/control";
constexpr char data_topic[] = "/vast/data";

constexpr char default_address[] = "localhost";
constexpr uint16_t default_port = 43000;

// Our custom configuration with extra command line options for this tool.
class config : public broker::configuration {
public:
  config() {
    // As a stand-alone application, we reuse the global option group from CAF
    // to avoid unnecessary prefixing.
    opt_group{custom_options_, "global"}
      .add<uint16_t>("port,p", "the port to listen at or connect to");
  }
};

// Constructs a result event for Bro.
broker::bro::Event make_bro_event(std::string id, broker::data x) {
  broker::vector args(2);
  args[0] = std::move(id);
  args[1] = std::move(x);
  return {"VAST::result", std::move(args)};
}

// A VAST writer that publishes the event it gets to a Bro endpoint.
class bro_writer {
public:
  bro_writer() = default;

  bro_writer(broker::endpoint& endpoint, std::string query_id)
    : endpoint_{&endpoint},
      query_id_{std::move(query_id)} {
    // nop
  }

  caf::expected<void> write(const vast::event& x) {
    // TODO: publish to Broker endpoint.
    std::cout << x.type().name() << std::endl;
    return caf::no_error;
  }

  caf::expected<void> flush() {
    return caf::no_error;
  }

  auto name() const {
    return "bro-writer";
  }

private:
  broker::endpoint* endpoint_;
  std::string query_id_;
};

// A custom command that allows us to re-use VAST command dispatching logic in
// order to issue a query that writes into a sink with a custom format.
class bro_command : public vast::system::writer_command_base {
public:
  bro_command(broker::endpoint& endpoint)
    : writer_command_base{nullptr, "bro"},
      endpoint_{endpoint} {
    // nop
  }

  // Sets the query ID to the UUID provided by Bro.
  void query_id(std::string id) {
    query_id_ = std::move(id);
  }

protected:
  caf::expected<caf::actor> make_sink(caf::scoped_actor& self,
                                      const caf::config_value_map& options,
                                      argument_iterator begin,
                                      argument_iterator end) override {
    VAST_UNUSED(options, begin, end);
    bro_writer writer{endpoint_, query_id_};
    return self->spawn(vast::system::sink<bro_writer>, std::move(writer),
                       vast::defaults::command::max_events);
  }

private:
  broker::endpoint& endpoint_;
  std::string query_id_;
};

// Parses Broker data as Bro event.
caf::expected<std::pair<std::string, std::string>>
parse_query_event(const broker::data& x) {
  std::pair<std::string, std::string> result;
  auto event = broker::bro::Event(x);
  if (event.name() != "VAST::query")
    return make_error(vast::ec::parse_error, "invalid event name", event.name());
  if (event.args().size() != 2)
    return make_error(vast::ec::parse_error, "invalid number of arguments");
  auto query_id = caf::get_if<std::string>(&event.args()[0]);
  if (!query_id)
    return make_error(vast::ec::parse_error, "invalid type of 1st argument");
  result.first = *query_id;
  if (!vast::parsers::uuid(*query_id))
    return make_error(vast::ec::parse_error, "invalid query UUID", *query_id);
  auto expression = caf::get_if<std::string>(&event.args()[1]);
  if (!expression)
    return make_error(vast::ec::parse_error, "invalid type of 2nd argument");
  if (!vast::parsers::expr(*expression))
    return make_error(vast::ec::parse_error, "invalid query expression",
                      *expression);
  result.second = *expression;
  return result;
}

} // namespace <anonymous>

int main(int argc, char** argv) {
  // Parse the command line.
  config cfg;
  vast::detail::add_message_types(cfg);
  cfg.parse(argc, argv);
  std::string address = caf::get_or(cfg, "address", default_address);
  uint16_t port = caf::get_or(cfg, "port", default_port);
  // Create a Broker endpoint.
  auto endpoint = broker::endpoint{std::move(cfg)};
  endpoint.listen(address, port);
  // Subscribe to the control channel.
  auto subscriber = endpoint.make_subscriber({control_topic});
  // Connect to VAST via a custom command.
  bro_command cmd{endpoint};
  auto& sys = endpoint.system();
  caf::scoped_actor self{sys};
  caf::config_value_map opts;
  auto node = cmd.connect_to_node(self, opts);
  if (!node) {
    std::cerr << "failed to connect to VAST: " << sys.render(node.error())
              << std::endl;
    return 1;
  }
  std::cerr << "connected to VAST successfully" << std::endl;
  // Block until Bro peers with us.
  auto receive_statuses = true;
  auto status_subscriber = endpoint.make_status_subscriber(receive_statuses);
  auto peered = false;
  while (!peered) {
    auto msg = status_subscriber.get();
    caf::visit(vast::detail::overload(
      [&](broker::none) {
        // timeout
      },
      [&](broker::error error) {
        std::cerr << sys.render(error) << std::endl;
      },
      [&](broker::status status) {
        if (status == broker::sc::peer_added)
          peered = true;
        else
          std::cerr << to_string(status) << std::endl;
      }
    ), msg);
  };
  std::cerr << "peered with Bro successfully" << std::endl;
  // Process queries from Bro.
  auto done = false;
  while (!done) {
    std::cerr << "waiting for commands" << std::endl;
    auto [topic, data] = subscriber.get();
    // Parse the Bro query event.
    auto result = parse_query_event(data);
    if (!result) {
      std::cerr << sys.render(result.error()) << std::endl;
      return 1;
    }
    auto& [query_id, expression] = *result;
    // Relay the query expression to VAST.
    cmd.query_id(query_id);
    auto args = std::vector<std::string>{expression};
    auto rc = cmd.run(sys, args.begin(), args.end());
    if (rc != 0) {
      std::cerr << "failed to dispatch query to VAST" << std::endl;
      return rc;
    }
    // A none value signals that the query has completed.
    endpoint.publish(data_topic, make_bro_event(query_id, broker::nil));
  }
}
<commit_msg>Add VAST error categories to Broker config<commit_after>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include <cstdint>
#include <iostream>
#include <string>

#include <caf/config_option_adder.hpp>

#include <broker/bro.hh>
#include <broker/broker.hh>

#include <vast/defaults.hpp>
#include <vast/error.hpp>
#include <vast/event.hpp>
#include <vast/expression.hpp>
#include <vast/uuid.hpp>

#include <vast/concept/parseable/parse.hpp>
#include <vast/concept/parseable/vast/expression.hpp>
#include <vast/concept/parseable/vast/uuid.hpp>

#include <vast/system/writer_command_base.hpp>
#include <vast/system/sink.hpp>

#include <vast/detail/add_error_categories.hpp>
#include <vast/detail/add_message_types.hpp>
#include <vast/detail/assert.hpp>
#include <vast/detail/overload.hpp>

namespace {

constexpr char control_topic[] = "/vast/control";
constexpr char data_topic[] = "/vast/data";

constexpr char default_address[] = "localhost";
constexpr uint16_t default_port = 43000;

// Our custom configuration with extra command line options for this tool.
class config : public broker::configuration {
public:
  config() {
    // As a stand-alone application, we reuse the global option group from CAF
    // to avoid unnecessary prefixing.
    opt_group{custom_options_, "global"}
      .add<uint16_t>("port,p", "the port to listen at or connect to");
  }
};

// Constructs a result event for Bro.
broker::bro::Event make_bro_event(std::string id, broker::data x) {
  broker::vector args(2);
  args[0] = std::move(id);
  args[1] = std::move(x);
  return {"VAST::result", std::move(args)};
}

// A VAST writer that publishes the event it gets to a Bro endpoint.
class bro_writer {
public:
  bro_writer() = default;

  bro_writer(broker::endpoint& endpoint, std::string query_id)
    : endpoint_{&endpoint},
      query_id_{std::move(query_id)} {
    // nop
  }

  caf::expected<void> write(const vast::event& x) {
    // TODO: publish to Broker endpoint.
    std::cout << x.type().name() << std::endl;
    return caf::no_error;
  }

  caf::expected<void> flush() {
    return caf::no_error;
  }

  auto name() const {
    return "bro-writer";
  }

private:
  broker::endpoint* endpoint_;
  std::string query_id_;
};

// A custom command that allows us to re-use VAST command dispatching logic in
// order to issue a query that writes into a sink with a custom format.
class bro_command : public vast::system::writer_command_base {
public:
  bro_command(broker::endpoint& endpoint)
    : writer_command_base{nullptr, "bro"},
      endpoint_{endpoint} {
    // nop
  }

  // Sets the query ID to the UUID provided by Bro.
  void query_id(std::string id) {
    query_id_ = std::move(id);
  }

protected:
  caf::expected<caf::actor> make_sink(caf::scoped_actor& self,
                                      const caf::config_value_map& options,
                                      argument_iterator begin,
                                      argument_iterator end) override {
    VAST_UNUSED(options, begin, end);
    bro_writer writer{endpoint_, query_id_};
    return self->spawn(vast::system::sink<bro_writer>, std::move(writer),
                       vast::defaults::command::max_events);
  }

private:
  broker::endpoint& endpoint_;
  std::string query_id_;
};

// Parses Broker data as Bro event.
caf::expected<std::pair<std::string, std::string>>
parse_query_event(const broker::data& x) {
  std::pair<std::string, std::string> result;
  auto event = broker::bro::Event(x);
  if (event.name() != "VAST::query")
    return make_error(vast::ec::parse_error, "invalid event name", event.name());
  if (event.args().size() != 2)
    return make_error(vast::ec::parse_error, "invalid number of arguments");
  auto query_id = caf::get_if<std::string>(&event.args()[0]);
  if (!query_id)
    return make_error(vast::ec::parse_error, "invalid type of 1st argument");
  result.first = *query_id;
  if (!vast::parsers::uuid(*query_id))
    return make_error(vast::ec::parse_error, "invalid query UUID", *query_id);
  auto expression = caf::get_if<std::string>(&event.args()[1]);
  if (!expression)
    return make_error(vast::ec::parse_error, "invalid type of 2nd argument");
  if (!vast::parsers::expr(*expression))
    return make_error(vast::ec::parse_error, "invalid query expression",
                      *expression);
  result.second = *expression;
  return result;
}

} // namespace <anonymous>

int main(int argc, char** argv) {
  // Parse the command line.
  config cfg;
  vast::detail::add_message_types(cfg);
  vast::detail::add_error_categories(cfg);
  cfg.parse(argc, argv);
  std::string address = caf::get_or(cfg, "address", default_address);
  uint16_t port = caf::get_or(cfg, "port", default_port);
  // Create a Broker endpoint.
  auto endpoint = broker::endpoint{std::move(cfg)};
  endpoint.listen(address, port);
  // Subscribe to the control channel.
  auto subscriber = endpoint.make_subscriber({control_topic});
  // Connect to VAST via a custom command.
  bro_command cmd{endpoint};
  auto& sys = endpoint.system();
  caf::scoped_actor self{sys};
  caf::config_value_map opts;
  auto node = cmd.connect_to_node(self, opts);
  if (!node) {
    std::cerr << "failed to connect to VAST: " << sys.render(node.error())
              << std::endl;
    return 1;
  }
  std::cerr << "connected to VAST successfully" << std::endl;
  // Block until Bro peers with us.
  auto receive_statuses = true;
  auto status_subscriber = endpoint.make_status_subscriber(receive_statuses);
  auto peered = false;
  while (!peered) {
    auto msg = status_subscriber.get();
    caf::visit(vast::detail::overload(
      [&](broker::none) {
        // timeout
      },
      [&](broker::error error) {
        std::cerr << sys.render(error) << std::endl;
      },
      [&](broker::status status) {
        if (status == broker::sc::peer_added)
          peered = true;
        else
          std::cerr << to_string(status) << std::endl;
      }
    ), msg);
  };
  std::cerr << "peered with Bro successfully" << std::endl;
  // Process queries from Bro.
  auto done = false;
  while (!done) {
    std::cerr << "waiting for commands" << std::endl;
    auto [topic, data] = subscriber.get();
    // Parse the Bro query event.
    auto result = parse_query_event(data);
    if (!result) {
      std::cerr << sys.render(result.error()) << std::endl;
      return 1;
    }
    auto& [query_id, expression] = *result;
    // Relay the query expression to VAST.
    cmd.query_id(query_id);
    auto args = std::vector<std::string>{expression};
    auto rc = cmd.run(sys, args.begin(), args.end());
    if (rc != 0) {
      std::cerr << "failed to dispatch query to VAST" << std::endl;
      return rc;
    }
    // A none value signals that the query has completed.
    endpoint.publish(data_topic, make_bro_event(query_id, broker::nil));
  }
}
<|endoftext|>


<commit_before>//===- CoverageReport.cpp - Code coverage report -------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class implements rendering of a code coverage report.
//
//===----------------------------------------------------------------------===//

#include "CoverageReport.h"
#include "RenderingSupport.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"

using namespace llvm;
namespace {
/// \brief Helper struct which prints trimmed and aligned columns.
struct Column {
  enum TrimKind { NoTrim, WidthTrim, LeftTrim, RightTrim };

  enum AlignmentKind { LeftAlignment, RightAlignment };

  StringRef Str;
  unsigned Width;
  TrimKind Trim;
  AlignmentKind Alignment;

  Column(StringRef Str, unsigned Width)
      : Str(Str), Width(Width), Trim(WidthTrim), Alignment(LeftAlignment) {}

  Column &set(TrimKind Value) {
    Trim = Value;
    return *this;
  }

  Column &set(AlignmentKind Value) {
    Alignment = Value;
    return *this;
  }

  void render(raw_ostream &OS) const;
};

raw_ostream &operator<<(raw_ostream &OS, const Column &Value) {
  Value.render(OS);
  return OS;
}
}

void Column::render(raw_ostream &OS) const {
  if (Str.size() <= Width) {
    if (Alignment == RightAlignment) {
      OS.indent(Width - Str.size());
      OS << Str;
      return;
    }
    OS << Str;
    OS.indent(Width - Str.size());
    return;
  }

  switch (Trim) {
  case NoTrim:
    OS << Str;
    break;
  case WidthTrim:
    OS << Str.substr(0, Width);
    break;
  case LeftTrim:
    OS << "..." << Str.substr(Str.size() - Width + 3);
    break;
  case RightTrim:
    OS << Str.substr(0, Width - 3) << "...";
    break;
  }
}

static Column column(StringRef Str, unsigned Width) {
  return Column(Str, Width);
}

template <typename T>
static Column column(StringRef Str, unsigned Width, const T &Value) {
  return Column(Str, Width).set(Value);
}

static size_t FileReportColumns[] = {25, 10, 8, 8, 10, 10};
static size_t FunctionReportColumns[] = {25, 10, 8, 8, 10, 8, 8};

/// \brief Prints a horizontal divider which spans across the given columns.
template <typename T, size_t N>
static void renderDivider(T (&Columns)[N], raw_ostream &OS) {
  unsigned Length = 0;
  for (unsigned I = 0; I < N; ++I)
    Length += Columns[I];
  for (unsigned I = 0; I < Length; ++I)
    OS << '-';
}

/// \brief Return the color which correponds to the coverage
/// percentage of a certain metric.
template <typename T>
static raw_ostream::Colors determineCoveragePercentageColor(const T &Info) {
  if (Info.isFullyCovered())
    return raw_ostream::GREEN;
  return Info.getPercentCovered() >= 80.0 ? raw_ostream::YELLOW
                                          : raw_ostream::RED;
}

void CoverageReport::render(const FileCoverageSummary &File, raw_ostream &OS) {
  OS << column(File.Name, FileReportColumns[0], Column::NoTrim)
     << format("%*u", FileReportColumns[1],
               (unsigned)File.RegionCoverage.NumRegions);
  Options.colored_ostream(OS, File.RegionCoverage.isFullyCovered()
                                  ? raw_ostream::GREEN
                                  : raw_ostream::RED)
      << format("%*u", FileReportColumns[2], (unsigned)File.RegionCoverage.NotCovered);
  Options.colored_ostream(OS,
                          determineCoveragePercentageColor(File.RegionCoverage))
      << format("%*.2f", FileReportColumns[3] - 1,
                File.RegionCoverage.getPercentCovered()) << '%';
  OS << format("%*u", FileReportColumns[4],
               (unsigned)File.FunctionCoverage.NumFunctions);
  Options.colored_ostream(
      OS, determineCoveragePercentageColor(File.FunctionCoverage))
      << format("%*.2f", FileReportColumns[5] - 1,
                File.FunctionCoverage.getPercentCovered()) << '%';
  OS << "\n";
}

void CoverageReport::render(const FunctionCoverageSummary &Function,
                            raw_ostream &OS) {
  OS << column(Function.Name, FunctionReportColumns[0], Column::RightTrim)
     << format("%*u", FunctionReportColumns[1],
               (unsigned)Function.RegionCoverage.NumRegions);
  Options.colored_ostream(OS, Function.RegionCoverage.isFullyCovered()
                                  ? raw_ostream::GREEN
                                  : raw_ostream::RED)
      << format("%*u", FunctionReportColumns[2],
                (unsigned)Function.RegionCoverage.NotCovered);
  Options.colored_ostream(
      OS, determineCoveragePercentageColor(Function.RegionCoverage))
      << format("%*.2f", FunctionReportColumns[3] - 1,
                Function.RegionCoverage.getPercentCovered()) << '%';
  OS << format("%*u", FunctionReportColumns[4],
               (unsigned)Function.LineCoverage.NumLines);
  Options.colored_ostream(OS, Function.LineCoverage.isFullyCovered()
                                  ? raw_ostream::GREEN
                                  : raw_ostream::RED)
      << format("%*u", FunctionReportColumns[5],
                (unsigned)Function.LineCoverage.NotCovered);
  Options.colored_ostream(
      OS, determineCoveragePercentageColor(Function.LineCoverage))
      << format("%*.2f", FunctionReportColumns[6] - 1,
                Function.LineCoverage.getPercentCovered()) << '%';
  OS << "\n";
}

void CoverageReport::renderFunctionReports(ArrayRef<std::string> Files,
                                           raw_ostream &OS) {
  bool isFirst = true;
  for (StringRef Filename : Files) {
    if (isFirst)
      isFirst = false;
    else
      OS << "\n";
    OS << "File '" << Filename << "':\n";
    OS << column("Name", FunctionReportColumns[0])
       << column("Regions", FunctionReportColumns[1], Column::RightAlignment)
       << column("Miss", FunctionReportColumns[2], Column::RightAlignment)
       << column("Cover", FunctionReportColumns[3], Column::RightAlignment)
       << column("Lines", FunctionReportColumns[4], Column::RightAlignment)
       << column("Miss", FunctionReportColumns[5], Column::RightAlignment)
       << column("Cover", FunctionReportColumns[6], Column::RightAlignment);
    OS << "\n";
    renderDivider(FunctionReportColumns, OS);
    OS << "\n";
    FunctionCoverageSummary Totals("TOTAL");
    for (const auto &F : Coverage->getCoveredFunctions(Filename)) {
      FunctionCoverageSummary Function = FunctionCoverageSummary::get(F);
      ++Totals.ExecutionCount;
      Totals.RegionCoverage += Function.RegionCoverage;
      Totals.LineCoverage += Function.LineCoverage;
      render(Function, OS);
    }
    if (Totals.ExecutionCount) {
      renderDivider(FunctionReportColumns, OS);
      OS << "\n";
      render(Totals, OS);
    }
  }
}

void CoverageReport::renderFileReports(raw_ostream &OS) {
  // Adjust column widths to accomodate long paths and names.
  for (StringRef Filename : Coverage->getUniqueSourceFiles()) {
    FileReportColumns[0] = std::max(FileReportColumns[0], Filename.size());
    for (const auto &F : Coverage->getCoveredFunctions(Filename)) {
      FunctionReportColumns[0] =
          std::max(FunctionReportColumns[0], F.Name.size());
    }
  }

  OS << column("Filename", FileReportColumns[0])
     << column("Regions", FileReportColumns[1], Column::RightAlignment)
     << column("Miss", FileReportColumns[2], Column::RightAlignment)
     << column("Cover", FileReportColumns[3], Column::RightAlignment)
     << column("Functions", FileReportColumns[4], Column::RightAlignment)
     << column("Executed", FileReportColumns[5], Column::RightAlignment)
     << "\n";
  renderDivider(FileReportColumns, OS);
  OS << "\n";

  FileCoverageSummary Totals("TOTAL");
  for (StringRef Filename : Coverage->getUniqueSourceFiles()) {
    FileCoverageSummary Summary(Filename);
    for (const auto &F : Coverage->getCoveredFunctions(Filename)) {
      FunctionCoverageSummary Function = FunctionCoverageSummary::get(F);
      Summary.addFunction(Function);
      Totals.addFunction(Function);
    }
    render(Summary, OS);
  }
  renderDivider(FileReportColumns, OS);
  OS << "\n";
  render(Totals, OS);
}
<commit_msg>[llvm-cov] Adjust column widths for function and file reports<commit_after>//===- CoverageReport.cpp - Code coverage report -------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class implements rendering of a code coverage report.
//
//===----------------------------------------------------------------------===//

#include "CoverageReport.h"
#include "RenderingSupport.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"

using namespace llvm;
namespace {
/// \brief Helper struct which prints trimmed and aligned columns.
struct Column {
  enum TrimKind { NoTrim, WidthTrim, LeftTrim, RightTrim };

  enum AlignmentKind { LeftAlignment, RightAlignment };

  StringRef Str;
  unsigned Width;
  TrimKind Trim;
  AlignmentKind Alignment;

  Column(StringRef Str, unsigned Width)
      : Str(Str), Width(Width), Trim(WidthTrim), Alignment(LeftAlignment) {}

  Column &set(TrimKind Value) {
    Trim = Value;
    return *this;
  }

  Column &set(AlignmentKind Value) {
    Alignment = Value;
    return *this;
  }

  void render(raw_ostream &OS) const;
};

raw_ostream &operator<<(raw_ostream &OS, const Column &Value) {
  Value.render(OS);
  return OS;
}
}

void Column::render(raw_ostream &OS) const {
  if (Str.size() <= Width) {
    if (Alignment == RightAlignment) {
      OS.indent(Width - Str.size());
      OS << Str;
      return;
    }
    OS << Str;
    OS.indent(Width - Str.size());
    return;
  }

  switch (Trim) {
  case NoTrim:
    OS << Str;
    break;
  case WidthTrim:
    OS << Str.substr(0, Width);
    break;
  case LeftTrim:
    OS << "..." << Str.substr(Str.size() - Width + 3);
    break;
  case RightTrim:
    OS << Str.substr(0, Width - 3) << "...";
    break;
  }
}

static Column column(StringRef Str, unsigned Width) {
  return Column(Str, Width);
}

template <typename T>
static Column column(StringRef Str, unsigned Width, const T &Value) {
  return Column(Str, Width).set(Value);
}

static size_t FileReportColumns[] = {25, 10, 8, 8, 10, 10};
static size_t FunctionReportColumns[] = {25, 10, 8, 8, 10, 8, 8};

/// \brief  Adjust column widths to fit long file paths and function names.
static void adjustColumnWidths(coverage::CoverageMapping *CM) {
  for (StringRef Filename : CM->getUniqueSourceFiles()) {
    FileReportColumns[0] = std::max(FileReportColumns[0], Filename.size());
    for (const auto &F : CM->getCoveredFunctions(Filename)) {
      FunctionReportColumns[0] =
          std::max(FunctionReportColumns[0], F.Name.size());
    }
  }
}

/// \brief Prints a horizontal divider which spans across the given columns.
template <typename T, size_t N>
static void renderDivider(T (&Columns)[N], raw_ostream &OS) {
  unsigned Length = 0;
  for (unsigned I = 0; I < N; ++I)
    Length += Columns[I];
  for (unsigned I = 0; I < Length; ++I)
    OS << '-';
}

/// \brief Return the color which correponds to the coverage
/// percentage of a certain metric.
template <typename T>
static raw_ostream::Colors determineCoveragePercentageColor(const T &Info) {
  if (Info.isFullyCovered())
    return raw_ostream::GREEN;
  return Info.getPercentCovered() >= 80.0 ? raw_ostream::YELLOW
                                          : raw_ostream::RED;
}

void CoverageReport::render(const FileCoverageSummary &File, raw_ostream &OS) {
  OS << column(File.Name, FileReportColumns[0], Column::NoTrim)
     << format("%*u", FileReportColumns[1],
               (unsigned)File.RegionCoverage.NumRegions);
  Options.colored_ostream(OS, File.RegionCoverage.isFullyCovered()
                                  ? raw_ostream::GREEN
                                  : raw_ostream::RED)
      << format("%*u", FileReportColumns[2], (unsigned)File.RegionCoverage.NotCovered);
  Options.colored_ostream(OS,
                          determineCoveragePercentageColor(File.RegionCoverage))
      << format("%*.2f", FileReportColumns[3] - 1,
                File.RegionCoverage.getPercentCovered()) << '%';
  OS << format("%*u", FileReportColumns[4],
               (unsigned)File.FunctionCoverage.NumFunctions);
  Options.colored_ostream(
      OS, determineCoveragePercentageColor(File.FunctionCoverage))
      << format("%*.2f", FileReportColumns[5] - 1,
                File.FunctionCoverage.getPercentCovered()) << '%';
  OS << "\n";
}

void CoverageReport::render(const FunctionCoverageSummary &Function,
                            raw_ostream &OS) {
  OS << column(Function.Name, FunctionReportColumns[0], Column::RightTrim)
     << format("%*u", FunctionReportColumns[1],
               (unsigned)Function.RegionCoverage.NumRegions);
  Options.colored_ostream(OS, Function.RegionCoverage.isFullyCovered()
                                  ? raw_ostream::GREEN
                                  : raw_ostream::RED)
      << format("%*u", FunctionReportColumns[2],
                (unsigned)Function.RegionCoverage.NotCovered);
  Options.colored_ostream(
      OS, determineCoveragePercentageColor(Function.RegionCoverage))
      << format("%*.2f", FunctionReportColumns[3] - 1,
                Function.RegionCoverage.getPercentCovered()) << '%';
  OS << format("%*u", FunctionReportColumns[4],
               (unsigned)Function.LineCoverage.NumLines);
  Options.colored_ostream(OS, Function.LineCoverage.isFullyCovered()
                                  ? raw_ostream::GREEN
                                  : raw_ostream::RED)
      << format("%*u", FunctionReportColumns[5],
                (unsigned)Function.LineCoverage.NotCovered);
  Options.colored_ostream(
      OS, determineCoveragePercentageColor(Function.LineCoverage))
      << format("%*.2f", FunctionReportColumns[6] - 1,
                Function.LineCoverage.getPercentCovered()) << '%';
  OS << "\n";
}

void CoverageReport::renderFunctionReports(ArrayRef<std::string> Files,
                                           raw_ostream &OS) {
  adjustColumnWidths(Coverage.get());
  bool isFirst = true;
  for (StringRef Filename : Files) {
    if (isFirst)
      isFirst = false;
    else
      OS << "\n";
    OS << "File '" << Filename << "':\n";
    OS << column("Name", FunctionReportColumns[0])
       << column("Regions", FunctionReportColumns[1], Column::RightAlignment)
       << column("Miss", FunctionReportColumns[2], Column::RightAlignment)
       << column("Cover", FunctionReportColumns[3], Column::RightAlignment)
       << column("Lines", FunctionReportColumns[4], Column::RightAlignment)
       << column("Miss", FunctionReportColumns[5], Column::RightAlignment)
       << column("Cover", FunctionReportColumns[6], Column::RightAlignment);
    OS << "\n";
    renderDivider(FunctionReportColumns, OS);
    OS << "\n";
    FunctionCoverageSummary Totals("TOTAL");
    for (const auto &F : Coverage->getCoveredFunctions(Filename)) {
      FunctionCoverageSummary Function = FunctionCoverageSummary::get(F);
      ++Totals.ExecutionCount;
      Totals.RegionCoverage += Function.RegionCoverage;
      Totals.LineCoverage += Function.LineCoverage;
      render(Function, OS);
    }
    if (Totals.ExecutionCount) {
      renderDivider(FunctionReportColumns, OS);
      OS << "\n";
      render(Totals, OS);
    }
  }
}

void CoverageReport::renderFileReports(raw_ostream &OS) {
  adjustColumnWidths(Coverage.get());
  OS << column("Filename", FileReportColumns[0])
     << column("Regions", FileReportColumns[1], Column::RightAlignment)
     << column("Miss", FileReportColumns[2], Column::RightAlignment)
     << column("Cover", FileReportColumns[3], Column::RightAlignment)
     << column("Functions", FileReportColumns[4], Column::RightAlignment)
     << column("Executed", FileReportColumns[5], Column::RightAlignment)
     << "\n";
  renderDivider(FileReportColumns, OS);
  OS << "\n";

  FileCoverageSummary Totals("TOTAL");
  for (StringRef Filename : Coverage->getUniqueSourceFiles()) {
    FileCoverageSummary Summary(Filename);
    for (const auto &F : Coverage->getCoveredFunctions(Filename)) {
      FunctionCoverageSummary Function = FunctionCoverageSummary::get(F);
      Summary.addFunction(Function);
      Totals.addFunction(Function);
    }
    render(Summary, OS);
  }
  renderDivider(FileReportColumns, OS);
  OS << "\n";
  render(Totals, OS);
}
<|endoftext|>


<commit_before>/* tests/win32/msgwnd.cpp
 *
 * Copyright (C) 2007 Antonio Di Monaco
 *
 * This software may be modified and distributed under the terms
 * of the MIT license.  See the LICENSE file for details.
 */

#include "tests/catch.hpp"

#include "win32/msgwnd.hpp"

TEST_CASE("Message window", "[Win32]")
{
  SECTION("send a message")
  {
    Windows::MsgWnd w(
      GetModuleHandle(NULL),
      [] (UINT uMsg, WPARAM wP, LPARAM lP)
        {
          REQUIRE(uMsg == (WM_USER + 1));
          REQUIRE(wP == static_cast< WPARAM >(0x01234567));
          REQUIRE(lP == static_cast< LPARAM >(0x89ABCDEF));
        });

    w.start();
    REQUIRE(w.handle() != NULL);

    SendMessage(w.handle(),WM_USER + 1,static_cast< WPARAM >(0x01234567),static_cast< LPARAM >(0x89ABCDEF));
  }
}

extern "C" int wmain(int argc, wchar_t **argv, wchar_t **)
{
  return run(argc,argv);
}
<commit_msg>Fixing msgwnd test<commit_after>/* tests/win32/msgwnd.cpp
 *
 * Copyright (C) 2007 Antonio Di Monaco
 *
 * This software may be modified and distributed under the terms
 * of the MIT license.  See the LICENSE file for details.
 */

#include "tests/catch.hpp"

#include "win32/msgwnd.hpp"
#include "win32/synch.hpp"

TEST_CASE("Message window", "[Win32]")
{
  SECTION("send a message")
  {
    Windows::Synch::Semaphore s(0,1);

    REQUIRE(s);

    bool flag = false;

    Windows::MsgWnd w(
      GetModuleHandle(NULL),
      [&s, &flag] (UINT uMsg, WPARAM wP, LPARAM lP)
        {
          if ((uMsg == (WM_USER + 1)) &&
              (wP == static_cast< WPARAM >(0x01234567)) &&
              (lP == static_cast< LPARAM >(0x89ABCDEF)))
            flag = true;

          s.release();
        });

    w.start();
    REQUIRE(w.handle() != NULL);

    PostMessage(
      w.handle(),
      WM_USER + 1,
      static_cast< WPARAM >(0x01234567),
      static_cast< LPARAM >(0x89ABCDEF));

    s.acquire();
    REQUIRE(flag);
  }
}

extern "C" int wmain(int argc, wchar_t **argv, wchar_t **)
{
  return run(argc,argv);
}
<|endoftext|>


<commit_before>/*******************************************************************************
 * thrill/mem/manager.hpp
 *
 * Part of Project Thrill.
 *
 * Copyright (C) 2015 Timo Bingmann <tb@panthema.net>
 *
 * This file has no license. Only Chuck Norris can compile it.
 ******************************************************************************/

#pragma once
#ifndef THRILL_MEM_MANAGER_HEADER
#define THRILL_MEM_MANAGER_HEADER

#include <algorithm>
#include <atomic>
#include <cassert>

namespace thrill {
namespace mem {

/*!
 * Object shared by allocators and other classes to track memory
 * allocations. These is one global mem::Manager per compute host. To track
 * memory consumption of subcomponents of Thrill, one can create local child
 * mem::Managers which report allocation automatically to their superiors.
 */
class Manager
{
    static const bool debug = true;

public:
    explicit Manager(Manager* super, const char* name)
        : super_(super), name_(name)
    { }

    ~Manager();

    //! return the superior Manager
    Manager * super() { return super_; }

    //! return total allocation (local value)
    size_t total() const { return total_; }

    //! add memory consumption.
    Manager & add(size_t amount) {
        size_t current = (total_ += amount);
        peak_ = std::max(peak_.load(), current);
        ++alloc_count_;
        if (super_) super_->add(amount);
        return *this;
    }

    //! subtract memory consumption.
    Manager & subtract(size_t amount) {
        assert(total_ >= amount);
        total_ -= amount;
        if (super_) super_->subtract(amount);
        return *this;
    }

protected:
    //! reference to superior memory counter
    Manager* super_;

    //! description for output
    const char* name_;

    //! total allocation
    std::atomic<size_t> total_ { 0 };

    //! peak allocation
    std::atomic<size_t> peak_ { 0 };

    //! number of allocation
    std::atomic<size_t> alloc_count_ { 0 };
};

} // namespace mem
} // namespace thrill

#endif // !THRILL_MEM_MANAGER_HEADER

/******************************************************************************/
<commit_msg>debug = false<commit_after>/*******************************************************************************
 * thrill/mem/manager.hpp
 *
 * Part of Project Thrill.
 *
 * Copyright (C) 2015 Timo Bingmann <tb@panthema.net>
 *
 * This file has no license. Only Chuck Norris can compile it.
 ******************************************************************************/

#pragma once
#ifndef THRILL_MEM_MANAGER_HEADER
#define THRILL_MEM_MANAGER_HEADER

#include <algorithm>
#include <atomic>
#include <cassert>

namespace thrill {
namespace mem {

/*!
 * Object shared by allocators and other classes to track memory
 * allocations. These is one global mem::Manager per compute host. To track
 * memory consumption of subcomponents of Thrill, one can create local child
 * mem::Managers which report allocation automatically to their superiors.
 */
class Manager
{
    static const bool debug = false;

public:
    explicit Manager(Manager* super, const char* name)
        : super_(super), name_(name)
    { }

    ~Manager();

    //! return the superior Manager
    Manager * super() { return super_; }

    //! return total allocation (local value)
    size_t total() const { return total_; }

    //! add memory consumption.
    Manager & add(size_t amount) {
        size_t current = (total_ += amount);
        peak_ = std::max(peak_.load(), current);
        ++alloc_count_;
        if (super_) super_->add(amount);
        return *this;
    }

    //! subtract memory consumption.
    Manager & subtract(size_t amount) {
        assert(total_ >= amount);
        total_ -= amount;
        if (super_) super_->subtract(amount);
        return *this;
    }

protected:
    //! reference to superior memory counter
    Manager* super_;

    //! description for output
    const char* name_;

    //! total allocation
    std::atomic<size_t> total_ { 0 };

    //! peak allocation
    std::atomic<size_t> peak_ { 0 };

    //! number of allocation
    std::atomic<size_t> alloc_count_ { 0 };
};

} // namespace mem
} // namespace thrill

#endif // !THRILL_MEM_MANAGER_HEADER

/******************************************************************************/
<|endoftext|>


<commit_before>/**
    @file ConnectionSTREAMEntry.cpp
    @author Lime Microsystems
    @brief Implementation of STREAM board connection.
*/

#include "ConnectionSTREAM.h"
#include <iostream>
using namespace lime;

#ifdef __unix__
void ConnectionSTREAMEntry::handle_libusb_events()
{
    struct timeval tv;
    tv.tv_sec = 0;
    tv.tv_usec = 250000;
    while(mProcessUSBEvents.load() == true)
    {
        int r = libusb_handle_events_timeout_completed(ctx, &tv, NULL);
        if(r != 0) printf("error libusb_handle_events %s\n", libusb_strerror(libusb_error(r)));
    }
}
#endif // __UNIX__

//! make a static-initialized entry in the registry
void __loadConnectionSTREAMEntry(void) //TODO fixme replace with LoadLibrary/dlopen
{
static ConnectionSTREAMEntry STREAMEntry;
}

int USBTransferContext::idCounter = 0;

ConnectionSTREAMEntry::ConnectionSTREAMEntry(void):
    ConnectionRegistryEntry("STREAM")
{
#ifdef __unix__
    int r = libusb_init(&ctx); //initialize the library for the session we just declared
    if(r < 0)
        printf("Init Error %i\n", r); //there was an error
    libusb_set_debug(ctx, 3); //set verbosity level to 3, as suggested in the documentation
    mProcessUSBEvents.store(true);
    mUSBProcessingThread = std::thread(&ConnectionSTREAMEntry::handle_libusb_events, this);
#endif
}

ConnectionSTREAMEntry::ConnectionSTREAMEntry(const std::string entryName):
    ConnectionRegistryEntry(entryName)
{
#ifdef __unix__
    int r = libusb_init(&ctx); //initialize the library for the session we just declared
    if(r < 0)
        printf("Init Error %i\n", r); //there was an error
    libusb_set_debug(ctx, 3); //set verbosity level to 3, as suggested in the documentation
    mProcessUSBEvents.store(true);
    mUSBProcessingThread = std::thread(&ConnectionSTREAMEntry::handle_libusb_events, this);
#endif
}

ConnectionSTREAMEntry::~ConnectionSTREAMEntry(void)
{
#ifdef __unix__
    mProcessUSBEvents.store(false);
    mUSBProcessingThread.join();
    libusb_exit(ctx);
#endif
}

#ifndef __unix__
/** @return name of usb device as string.
    @param index device index in list
*/
std::string ConnectionSTREAMEntry::DeviceName(unsigned int index)
{
    std::string name;
    char tempName[USB_STRING_MAXLEN];
    CCyUSBDevice device;
    if (index >= device.DeviceCount())
        return "";

    for (int i = 0; i < USB_STRING_MAXLEN; ++i)
            tempName[i] = device.DeviceName[i];
    if (device.bSuperSpeed == true)
        name = "USB 3.0";
    else if (device.bHighSpeed == true)
        name = "USB 2.0";
    else
        name = "USB";
    name += " (";
    name += tempName;
    name += ")";
    return name;
}
#endif

std::vector<ConnectionHandle> ConnectionSTREAMEntry::enumerate(const ConnectionHandle &hint)
{
    std::vector<ConnectionHandle> handles;

#ifndef __unix__
	CCyUSBDevice device;
	if (device.DeviceCount())
    {
		for (int i = 0; i<device.DeviceCount(); ++i)
        {
			if (hint.index >= 0 && hint.index != i)
				continue;
			if (device.IsOpen())
				device.Close();
            device.Open(i);
            ConnectionHandle handle;
            handle.media = "USB";
            handle.name = DeviceName(i);
            handle.index = i;
            std::wstring ws(device.SerialNumber);
            handle.serial = std::string(ws.begin(),ws.end());
            if (hint.serial.empty() or hint.serial == handle.serial)
            {
                handles.push_back(handle); //filter on serial
            }
            device.Close();
        }
    }
#else
    libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices
    int usbDeviceCount = libusb_get_device_list(ctx, &devs);
    if(usbDeviceCount > 0)
    {
        for(int i=0; i<usbDeviceCount; ++i)
        {
            libusb_device_descriptor desc;
            int r = libusb_get_device_descriptor(devs[i], &desc);
            if(r<0)
                printf("failed to get device description\n");
            int pid = desc.idProduct;
            int vid = desc.idVendor;

            if(vid == 1204 && pid == 34323)
            {
                ConnectionHandle handle;
                handle.media = "USB";
                handle.name = "DigiGreen";
                handle.addr = std::to_string(int(pid))+":"+std::to_string(int(vid));
                handles.push_back(handle);
            }
            else if((vid == 1204 && pid == 241) || (vid == 1204 && pid == 243) || (vid == 7504 && pid == 24840))
            {
                libusb_device_handle *tempDev_handle(nullptr);
                if(libusb_open(devs[i], &tempDev_handle) != 0 || tempDev_handle == nullptr)
                    continue;
                if(libusb_kernel_driver_active(tempDev_handle, 0) == 1)   //find out if kernel driver is attached
                {
                    if(libusb_detach_kernel_driver(tempDev_handle, 0) == 0) //detach it
                        printf("Kernel Driver Detached!\n");
                }
                if(libusb_claim_interface(tempDev_handle, 0) < 0) //claim interface 0 (the first) of device
                {
                    printf("Cannot Claim Interface\n");
                }

                std::string fullName;
                //check operating speed
                int speed = libusb_get_device_speed(devs[i]);
                if(speed == LIBUSB_SPEED_HIGH)
                    fullName = "USB 2.0";
                else if(speed == LIBUSB_SPEED_SUPER)
                    fullName = "USB 3.0";
                else
                    fullName = "USB";
                fullName += " (";
                //read device name
                char data[255];
                r = libusb_get_string_descriptor_ascii(tempDev_handle,  LIBUSB_CLASS_COMM, (unsigned char*)data, sizeof(data));
                if(r > 0) fullName += std::string(data, size_t(r));
                fullName += ")";

                ConnectionHandle handle;
                handle.media = "USB";
                handle.name = fullName;
                r = std::sprintf(data, "%.4x:%.4x", int(vid), int(pid));
                if (r > 0) handle.addr = std::string(data, size_t(r));

                if (desc.iSerialNumber > 0)
                {
                    r = libusb_get_string_descriptor_ascii(tempDev_handle,desc.iSerialNumber,(unsigned char*)data, sizeof(data));
                    if(r<0)
                        printf("failed to get serial number\n");
                    else
                        handle.serial = std::string(data, size_t(r));
                }
                libusb_close(tempDev_handle);

                //add handle conditionally, filter by serial number
                if (hint.serial.empty() or hint.serial == handle.serial)
                {
                    handles.push_back(handle);
                }
            }
        }
    }
    else
    {
        libusb_free_device_list(devs, 1);
    }
#endif
    return handles;
}

IConnection *ConnectionSTREAMEntry::make(const ConnectionHandle &handle)
{
    return new ConnectionSTREAM(ctx, handle.addr, handle.serial, handle.index);
}
<commit_msg>limesdr - enumerate set media and device name<commit_after>/**
    @file ConnectionSTREAMEntry.cpp
    @author Lime Microsystems
    @brief Implementation of STREAM board connection.
*/

#include "ConnectionSTREAM.h"
#include <iostream>
using namespace lime;

#ifdef __unix__
void ConnectionSTREAMEntry::handle_libusb_events()
{
    struct timeval tv;
    tv.tv_sec = 0;
    tv.tv_usec = 250000;
    while(mProcessUSBEvents.load() == true)
    {
        int r = libusb_handle_events_timeout_completed(ctx, &tv, NULL);
        if(r != 0) printf("error libusb_handle_events %s\n", libusb_strerror(libusb_error(r)));
    }
}
#endif // __UNIX__

//! make a static-initialized entry in the registry
void __loadConnectionSTREAMEntry(void) //TODO fixme replace with LoadLibrary/dlopen
{
static ConnectionSTREAMEntry STREAMEntry;
}

int USBTransferContext::idCounter = 0;

ConnectionSTREAMEntry::ConnectionSTREAMEntry(void):
    ConnectionRegistryEntry("STREAM")
{
#ifdef __unix__
    int r = libusb_init(&ctx); //initialize the library for the session we just declared
    if(r < 0)
        printf("Init Error %i\n", r); //there was an error
    libusb_set_debug(ctx, 3); //set verbosity level to 3, as suggested in the documentation
    mProcessUSBEvents.store(true);
    mUSBProcessingThread = std::thread(&ConnectionSTREAMEntry::handle_libusb_events, this);
#endif
}

ConnectionSTREAMEntry::ConnectionSTREAMEntry(const std::string entryName):
    ConnectionRegistryEntry(entryName)
{
#ifdef __unix__
    int r = libusb_init(&ctx); //initialize the library for the session we just declared
    if(r < 0)
        printf("Init Error %i\n", r); //there was an error
    libusb_set_debug(ctx, 3); //set verbosity level to 3, as suggested in the documentation
    mProcessUSBEvents.store(true);
    mUSBProcessingThread = std::thread(&ConnectionSTREAMEntry::handle_libusb_events, this);
#endif
}

ConnectionSTREAMEntry::~ConnectionSTREAMEntry(void)
{
#ifdef __unix__
    mProcessUSBEvents.store(false);
    mUSBProcessingThread.join();
    libusb_exit(ctx);
#endif
}

#ifndef __unix__
/** @return name of usb device as string.
    @param index device index in list
*/
std::string ConnectionSTREAMEntry::DeviceName(unsigned int index)
{
    std::string name;
    char tempName[USB_STRING_MAXLEN];
    CCyUSBDevice device;
    if (index >= device.DeviceCount())
        return "";

    for (int i = 0; i < USB_STRING_MAXLEN; ++i)
            tempName[i] = device.DeviceName[i];
    if (device.bSuperSpeed == true)
        name = "USB 3.0";
    else if (device.bHighSpeed == true)
        name = "USB 2.0";
    else
        name = "USB";
    name += " (";
    name += tempName;
    name += ")";
    return name;
}
#endif

std::vector<ConnectionHandle> ConnectionSTREAMEntry::enumerate(const ConnectionHandle &hint)
{
    std::vector<ConnectionHandle> handles;

#ifndef __unix__
	CCyUSBDevice device;
	if (device.DeviceCount())
    {
		for (int i = 0; i<device.DeviceCount(); ++i)
        {
			if (hint.index >= 0 && hint.index != i)
				continue;
			if (device.IsOpen())
				device.Close();
            device.Open(i);
            ConnectionHandle handle;
            handle.media = "USB";
            handle.name = DeviceName(i);
            handle.index = i;
            std::wstring ws(device.SerialNumber);
            handle.serial = std::string(ws.begin(),ws.end());
            if (hint.serial.empty() or hint.serial == handle.serial)
            {
                handles.push_back(handle); //filter on serial
            }
            device.Close();
        }
    }
#else
    libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices
    int usbDeviceCount = libusb_get_device_list(ctx, &devs);
    if(usbDeviceCount > 0)
    {
        for(int i=0; i<usbDeviceCount; ++i)
        {
            libusb_device_descriptor desc;
            int r = libusb_get_device_descriptor(devs[i], &desc);
            if(r<0)
                printf("failed to get device description\n");
            int pid = desc.idProduct;
            int vid = desc.idVendor;

            if(vid == 1204 && pid == 34323)
            {
                ConnectionHandle handle;
                handle.media = "USB";
                handle.name = "DigiGreen";
                handle.addr = std::to_string(int(pid))+":"+std::to_string(int(vid));
                handles.push_back(handle);
            }
            else if((vid == 1204 && pid == 241) || (vid == 1204 && pid == 243) || (vid == 7504 && pid == 24840))
            {
                libusb_device_handle *tempDev_handle(nullptr);
                if(libusb_open(devs[i], &tempDev_handle) != 0 || tempDev_handle == nullptr)
                    continue;
                if(libusb_kernel_driver_active(tempDev_handle, 0) == 1)   //find out if kernel driver is attached
                {
                    if(libusb_detach_kernel_driver(tempDev_handle, 0) == 0) //detach it
                        printf("Kernel Driver Detached!\n");
                }
                if(libusb_claim_interface(tempDev_handle, 0) < 0) //claim interface 0 (the first) of device
                {
                    printf("Cannot Claim Interface\n");
                }

                ConnectionHandle handle;

                //check operating speed
                int speed = libusb_get_device_speed(devs[i]);
                if(speed == LIBUSB_SPEED_HIGH)
                    handle.media = "USB 2.0";
                else if(speed == LIBUSB_SPEED_SUPER)
                    handle.media = "USB 3.0";
                else
                    handle.media = "USB";

                //read device name
                char data[255];
                r = libusb_get_string_descriptor_ascii(tempDev_handle,  LIBUSB_CLASS_COMM, (unsigned char*)data, sizeof(data));
                if(r > 0) handle.name = std::string(data, size_t(r));

                r = std::sprintf(data, "%.4x:%.4x", int(vid), int(pid));
                if (r > 0) handle.addr = std::string(data, size_t(r));

                if (desc.iSerialNumber > 0)
                {
                    r = libusb_get_string_descriptor_ascii(tempDev_handle,desc.iSerialNumber,(unsigned char*)data, sizeof(data));
                    if(r<0)
                        printf("failed to get serial number\n");
                    else
                        handle.serial = std::string(data, size_t(r));
                }
                libusb_close(tempDev_handle);

                //add handle conditionally, filter by serial number
                if (hint.serial.empty() or hint.serial == handle.serial)
                {
                    handles.push_back(handle);
                }
            }
        }
    }
    else
    {
        libusb_free_device_list(devs, 1);
    }
#endif
    return handles;
}

IConnection *ConnectionSTREAMEntry::make(const ConnectionHandle &handle)
{
    return new ConnectionSTREAM(ctx, handle.addr, handle.serial, handle.index);
}
<|endoftext|>


<commit_before>#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
    ofSetVerticalSync(true);
    renderEngine = NULL;

    ofxMultiGLFWWindow *glfw = (ofxMultiGLFWWindow*)ofGetWindowPtr();

    //Look for number of monitors
    //
    int numberOfMonitors;
	GLFWmonitor** monitors = glfwGetMonitors(&numberOfMonitors);
    cout<<"Num windows: "<<numberOfMonitors<<endl;

    // Setup the render views
    //
    if(numberOfMonitors == 3){

        //Set the main window to full HD
        ofSetWindowShape(1920, 1080);

        //Find the positions of the monitors
        //
        vector<ofRectangle> monitorSizes;
        for (int iC=0; iC < numberOfMonitors; iC++){
            int xM; int yM;
            glfwGetMonitorPos(monitors[iC], &xM, &yM);
            const GLFWvidmode * desktopMode = glfwGetVideoMode(monitors[iC]);
            ofRectangle monitorRect(xM, yM, desktopMode->width, desktopMode->height);
            monitorSizes.push_back(monitorRect);
        }

        //Run through the windows, and create the additional render views
        for(int i=0;i<2;i++){
            GLFWwindow * window = glfw->createWindow();
            glfw->setWindow(window);

            if(i==0){
                ofSetWindowPosition(monitorSizes[0].width + 200, 100);
            } else {
                ofSetWindowPosition(monitorSizes[0].width + monitorSizes[1].width + 200, 100);
                ofToggleFullscreen();
            }
            ofToggleFullscreen();
        }

        glfw->setWindow(glfw->windows.at(0));
        glfw->showWindow(glfw->windows.at(0));

    } else {
        ofToggleFullscreen();
    }

    //  Load STUFF
    //
    calibration.load();
    renderAssets.load();

    imageQueue.loadQueueFromFile();

    //  SETUP Node
    //
    nodeCommunication.imageQueue = &imageQueue;
    nodeCommunication.setup();

    // SETUP audio trigger
    audioTrigger.setup();

    //  start the RENDER
    //
    loadAnimation();
}

void ofApp::loadAnimation(){

    if (renderEngine != NULL){
        renderEngine->stop();
        delete renderEngine;
        renderEngine = NULL;
    }

    renderEngine = new RenderRadar();

    //  Link renderEngine to ImageQueue
    //
    imageQueue.renderEngine = renderEngine;

    //  Loading Resources (this could be pointers)
    //
    renderEngine->assets = &renderAssets;

    //  Setup The RenderEngine
    //
	renderEngine->setup();

    renderEngine->addUIClass(&imageQueue);
    renderEngine->addUIClass(&nodeCommunication);
    renderEngine->addUIClass(&audioTrigger);
    renderEngine->setCalibration(&calibration);

    //  Ready to GO
    //
	renderEngine->play();
    renderEngine->getTimeline()->setDurationInSeconds(5);
}

//--------------------------------------------------------------
void ofApp::update(){
    nodeCommunication.update();
    imageQueue.update();
}

//--------------------------------------------------------------
void ofApp::draw(){

}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){

}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){

}
<commit_msg>fullscreen on secondary monitor if one<commit_after>#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
    ofSetVerticalSync(true);
    renderEngine = NULL;

    ofxMultiGLFWWindow *glfw = (ofxMultiGLFWWindow*)ofGetWindowPtr();

    //Look for number of monitors
    //
    int numberOfMonitors;
	GLFWmonitor** monitors = glfwGetMonitors(&numberOfMonitors);
    cout<<"Num windows: "<<numberOfMonitors<<endl;

    // Setup the render views
    //
    if(numberOfMonitors == 3){

        //Set the main window to full HD
        ofSetWindowShape(1920, 1080);

        //Find the positions of the monitors
        //
        vector<ofRectangle> monitorSizes;
        for (int iC=0; iC < numberOfMonitors; iC++){
            int xM; int yM;
            glfwGetMonitorPos(monitors[iC], &xM, &yM);
            const GLFWvidmode * desktopMode = glfwGetVideoMode(monitors[iC]);
            ofRectangle monitorRect(xM, yM, desktopMode->width, desktopMode->height);
            monitorSizes.push_back(monitorRect);
        }

        //Run through the windows, and create the additional render views
        for(int i=0;i<2;i++){
            GLFWwindow * window = glfw->createWindow();
            glfw->setWindow(window);

            if(i==0){
                ofSetWindowPosition(monitorSizes[0].width + 200, 100);
            } else {
                ofSetWindowPosition(monitorSizes[0].width + monitorSizes[1].width + 200, 100);
                ofToggleFullscreen();
            }
            ofToggleFullscreen();
        }

        glfw->setWindow(glfw->windows.at(0));
        glfw->showWindow(glfw->windows.at(0));

    } else if(numberOfMonitors == 2){

        //Find the positions of the monitors
        //
        vector<ofRectangle> monitorSizes;
        for (int iC=0; iC < numberOfMonitors; iC++){
            int xM; int yM;
            glfwGetMonitorPos(monitors[iC], &xM, &yM);
            const GLFWvidmode * desktopMode = glfwGetVideoMode(monitors[iC]);
            ofRectangle monitorRect(xM, yM, desktopMode->width, desktopMode->height);
            monitorSizes.push_back(monitorRect);
        }

        ofSetWindowPosition(monitorSizes[0].width + 200, 100);
        ofSetFullscreen(true);

    } else {
        ofToggleFullscreen();
    }

    //  Load STUFF
    //
    calibration.load();
    renderAssets.load();

    imageQueue.loadQueueFromFile();

    //  SETUP Node
    //
    nodeCommunication.imageQueue = &imageQueue;
    nodeCommunication.setup();

    // SETUP audio trigger
    audioTrigger.setup();

    //  start the RENDER
    //
    loadAnimation();
}

void ofApp::loadAnimation(){

    if (renderEngine != NULL){
        renderEngine->stop();
        delete renderEngine;
        renderEngine = NULL;
    }

    renderEngine = new RenderRadar();

    //  Link renderEngine to ImageQueue
    //
    imageQueue.renderEngine = renderEngine;

    //  Loading Resources (this could be pointers)
    //
    renderEngine->assets = &renderAssets;

    //  Setup The RenderEngine
    //
	renderEngine->setup();

    renderEngine->addUIClass(&imageQueue);
    renderEngine->addUIClass(&nodeCommunication);
    renderEngine->addUIClass(&audioTrigger);
    renderEngine->setCalibration(&calibration);

    //  Ready to GO
    //
	renderEngine->play();
    renderEngine->getTimeline()->setDurationInSeconds(5);
}

//--------------------------------------------------------------
void ofApp::update(){
    nodeCommunication.update();
    imageQueue.update();
}

//--------------------------------------------------------------
void ofApp::draw(){

}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){

}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){

}
<|endoftext|>


<commit_before>#include "tcpserver.h"

#include "util/net.h"

using namespace std;
using namespace happyntrain::network;
using namespace happyntrain::fd;

namespace happyntrain {

class TCPChannel;

TCPChannel::TCPChannel(EventLoop* eventloop, ConnectionSocketFD&& connectionSocket)
    : state_(State::INVALID),
      channel_(nullptr),
      eventloop_(eventloop),
      address_(0),
      connectionSocket_(std::forward<ConnectionSocketFD>(connectionSocket)),
      inBuffer_(),
      predictInBufferSize_(1 << 7),
      outBuffer_(),
      dataListener_(nullptr)
      {}

TCPChannel::~TCPChannel() {}

void TCPChannel::Send(std::string msg) {}

void TCPChannel::Close() {}

// Register channel to eventloop
// including selector, events, and event-callback
void TCPChannel::Register(Ref<TCPChannel> self) {
  channel_ = eventloop_->RegisterChannel(connectionSocket_);
  // TODO: should register kWriteEventFlag ?
  channel_->SetReadEnable();
  state_ = State::CONNECTED;
  channel_->OnRead([self] { self->OnReadable(); });
}

void TCPChannel::OnReadable() {
  if (state_ != State::CONNECTED) {
    WARN("connection fd(%d) not in connected state", channel_->fd());
    // TODO: handle exception
    return;
  }

  const size_t maxBufferSize = 1 << 15;

  while (state_ == State::CONNECTED) {
    Ptr<char[]> buffer(new char[predictInBufferSize_]);
    ssize_t actualReadSize = connectionSocket_.read(buffer.get(), predictInBufferSize_);
    DEBUG("Channel id(%lu) fd(%d) read(%zu/%zd)",
      channel_->id(), channel_->fd(), actualReadSize, predictInBufferSize_);

    if (actualReadSize == -1) {
      int err = connectionSocket_.err();
      if (err == EAGAIN || err == EWOULDBLOCK) {
        FinishNonBlockingRead();
        break;
      } else if (err == EINTR)  // interrupted
        continue;
      else {
        break;
      }
    } else if (actualReadSize == 0) {
      break;
    } else {
      inBuffer_.append(buffer.get(), predictInBufferSize_);
      if (actualReadSize == predictInBufferSize_ && predictInBufferSize_ < maxBufferSize) {
        predictInBufferSize_ <<= 1;
      }
    }
  }
}

void TCPChannel::FinishNonBlockingRead() {
  DEBUG("Buffer(%s)", inBuffer_.str().c_str());
  if (dataListener_) {
    dataListener_(shared_from_this(), inBuffer_);
  }
  else {
    inBuffer_.clear();
  }
}

// -------------------
class TCPServer;
//--------------------

TCPServer::TCPServer()
    : listenChannel_(nullptr),
      eventloop_(nullptr),
      address_("127.0.0.1", 12346) {}

TCPServer::TCPServer(EventLoop* eventloop)
    : listenChannel_(nullptr),
      eventloop_(eventloop),
      address_("127.0.0.1", 12346) {}

void TCPServer::Listen(int port) {
  address_ = IP4Address(port);
  Listen();
}

void TCPServer::Listen() {
  ServerSocketFD listenFD;
  Bind(listenFD);
  EXIT_IF(listenFD.listen(128) == false, "fd(%d) listen to port(%d) failed",
          listenFD.fd(), address_.port);
  INFO("fd(%d) is now listening on port(%d)", listenFD.fd(), address_.port);
  listenChannel_ = eventloop_->RegisterChannel(listenFD);
  listenChannel_->SetReadEnable().OnRead([this]() { OnAcceptable(); });
}

void TCPServer::Bind(ServerSocketFD& listenFD) {
  // Fail the program if these fail
  EXIT_IF(listenFD.invalid(), "create listen socket fd failed");
  EXIT_IF(listenFD.setNonBlock() == false, "fd(%d) set NONBLOCK fail",
          listenFD.fd());

  // Still go on even if these fail
  EXPECT(listenFD.setReusePort(), "fd(%d) set REUSEPORT fail", listenFD.fd());
  EXPECT(listenFD.setCloseOnExec(), "fd(%d) set CLOSEONEXEC fail",
         listenFD.fd());

  EXIT_IF(listenFD.bind(address_.host, address_.port) == false,
          "fd(%d) bind port(%d) failed", listenFD.fd(), address_.port);
}

void TCPServer::OnAcceptable() {
  const int listenFD = listenChannel_->fd();
  while (true) {
    ConnectionSocketFD connectionSocket(listenFD);
    if (connectionSocket.invalid()) {
      if (connectionSocket.err() != EAGAIN && connectionSocket.err() != EINTR)
        ERROR("accept connection failed on listen fd(%d)", listenFD);
      break;
    }
    DEBUG("accept connection fd(%d) succeed on listen fd(%d)", connectionSocket.fd(), listenFD);
    Ref<TCPChannel> connection = newInstance<TCPChannel>(eventloop_, std::move(connectionSocket));
    connection->Register(connection);
    // connected !
    OnConnect();
  }
}

void TCPServer::OnConnect() {

}

// end happytrain
}<commit_msg>Fix: apppend autual read size to buffer<commit_after>#include "tcpserver.h"

#include "util/net.h"

using namespace std;
using namespace happyntrain::network;
using namespace happyntrain::fd;

namespace happyntrain {

class TCPChannel;

TCPChannel::TCPChannel(EventLoop* eventloop, ConnectionSocketFD&& connectionSocket)
    : state_(State::INVALID),
      channel_(nullptr),
      eventloop_(eventloop),
      address_(0),
      connectionSocket_(std::forward<ConnectionSocketFD>(connectionSocket)),
      inBuffer_(),
      predictInBufferSize_(1 << 7),
      outBuffer_(),
      dataListener_(nullptr)
      {}

TCPChannel::~TCPChannel() {}

void TCPChannel::Send(std::string msg) {}

void TCPChannel::Close() {}

// Register channel to eventloop
// including selector, events, and event-callback
void TCPChannel::Register() {
  channel_ = eventloop_->RegisterChannel(connectionSocket_);
  // TODO: should register kWriteEventFlag ?
  channel_->SetReadEnable();
  state_ = State::CONNECTED;
  auto self = shared_from_this();
  channel_->OnRead([self] { self->OnReadable(); });
}

void TCPChannel::OnReadable() {
  if (state_ != State::CONNECTED) {
    WARN("connection fd(%d) not in connected state", channel_->fd());
    // TODO: handle exception
    return;
  }

  const size_t maxBufferSize = 1 << 15;

  while (state_ == State::CONNECTED) {
    Ptr<char[]> buffer(new char[predictInBufferSize_]);
    ssize_t actualReadSize = connectionSocket_.read(buffer.get(), predictInBufferSize_);
    DEBUG("Channel id(%lu) fd(%d) read(%zd/%zu)",
      channel_->id(), channel_->fd(), actualReadSize, predictInBufferSize_);

    if (actualReadSize == -1) {
      int err = connectionSocket_.err();
      if (err == EAGAIN || err == EWOULDBLOCK) {
        FinishNonBlockingRead();
        break;
      } else if (err == EINTR)  // interrupted
        continue;
      else {
        break;
      }
    } else if (actualReadSize == 0) {
      break;
    } else {
      inBuffer_.append(buffer.get(), actualReadSize);
      if (actualReadSize == predictInBufferSize_ && predictInBufferSize_ < maxBufferSize) {
        predictInBufferSize_ <<= 1;
      }
    }
  }
}

void TCPChannel::FinishNonBlockingRead() {
  DEBUG("Buffer(%s)", inBuffer_.str().c_str());
  if (dataListener_) {
    dataListener_(shared_from_this(), inBuffer_);
  }
  else {
    inBuffer_.clear();
  }
}

// -------------------
class TCPServer;
//--------------------

TCPServer::TCPServer()
    : listenChannel_(nullptr),
      eventloop_(nullptr),
      address_("127.0.0.1", 12346) {}

TCPServer::TCPServer(EventLoop* eventloop)
    : listenChannel_(nullptr),
      eventloop_(eventloop),
      address_("127.0.0.1", 12346) {}

void TCPServer::Listen(int port) {
  address_ = IP4Address(port);
  Listen();
}

void TCPServer::Listen() {
  ServerSocketFD listenFD;
  Bind(listenFD);
  EXIT_IF(listenFD.listen(128) == false, "fd(%d) listen to port(%d) failed",
          listenFD.fd(), address_.port);
  INFO("Server Socket FD(%d) is now listening on port(%d)", listenFD.fd(), address_.port);
  listenChannel_ = eventloop_->RegisterChannel(listenFD);
  listenChannel_->SetReadEnable().OnRead([this] { this->OnAcceptable(); });
}

void TCPServer::Bind(ServerSocketFD& listenFD) {
  // Fail the program if these fail
  EXIT_IF(listenFD.invalid(), "Create Server Socket fd failed");
  EXIT_IF(listenFD.setNonBlock() == false, "Server Socket fd(%d) set NONBLOCK fail",
          listenFD.fd());

  // Still go on even if these fail
  EXPECT(listenFD.setReusePort(), "Server Socket fd(%d) set REUSEPORT fail", listenFD.fd());
  EXPECT(listenFD.setCloseOnExec(), "Server Socket fd(%d) set CLOSEONEXEC fail",
         listenFD.fd());

  EXIT_IF(listenFD.bind(address_.host, address_.port) == false,
          "Server Socket fd(%d) bind port(%d) failed", listenFD.fd(), address_.port);
}

void TCPServer::OnAcceptable() {
  const int listenFD = listenChannel_->fd();
  while (true) {
    ConnectionSocketFD connectionSocket(listenFD);
    if (connectionSocket.invalid()) {
      if (connectionSocket.err() != EAGAIN && connectionSocket.err() != EINTR)
        ERROR("Accept connection failed on Server Socket fd(%d)", listenFD);
      break;
    }
    DEBUG("Accept connection fd(%d) succeed on Server Socket fd(%d)", connectionSocket.fd(), listenFD);
    Ref<TCPChannel> connection = newInstance<TCPChannel>(eventloop_, std::move(connectionSocket));
    connection->Register();
    // connected !
    OnConnect();
  }
}

void TCPServer::OnConnect() {

}

// end happytrain
}<|endoftext|>


<commit_before>#include <boost/test/unit_test.hpp>
#include "client/Client.hpp"
#include "client/SocketFactory.hpp"
#include "server/CoreServer.hpp"
#include "net/Cert.hpp"
#include "net/Net.hpp"
#include "net/TcpSocket.hpp"
#include "Response.hpp"
#include "../TestThread.hpp"
#include <thread>

using namespace http;

BOOST_AUTO_TEST_SUITE(TestCoreServer)

static const uint16_t BASE_PORT = 5100;

class Server : public http::CoreServer
{
protected:
    virtual http::Response handle_request(http::Request &)override
    {
        http::Response resp;
        resp.status_code(200);
        resp.headers.add("Content-Type", "text/plain");
        resp.body = "OK";
        return resp;
    }
    virtual http::Response parser_error_page(const http::ParserError &)override
    {
        throw std::runtime_error("Unexpected parser_error_page");
    }
};

void success_server_thread(Server *server)
{
    server->run();
}
BOOST_AUTO_TEST_CASE(success)
{
    TestThread server_thread;
    Server server;
    server.add_tcp_listener("127.0.0.1", BASE_PORT + 0);
    server.add_tls_listener("127.0.0.1", BASE_PORT + 1, load_pfx_cert("localhost.pfx", "password"));
    server.add_tls_listener("127.0.0.1", BASE_PORT + 2, load_pfx_cert("wrong-host.pfx", "password"));

    server_thread = TestThread(std::bind(&Server::run, &server));

    http::DefaultSocketFactory socket_factory;

    {
        // http://
        http::Request req;
        req.method = GET;
        req.headers.add("Host", "localhost");
        req.raw_url = "/index.html";

        auto resp = http::Client("localhost", BASE_PORT + 0, false, &socket_factory).make_request(req);

        BOOST_CHECK_EQUAL(200, resp.status.code);
        BOOST_CHECK_EQUAL("OK", resp.body);
    }
    {
        // https:// - TLS
        http::Request req;
        req.method = GET;
        req.headers.add("Host", "localhost");
        req.raw_url = "/index.html";

        auto resp = http::Client("localhost", BASE_PORT + 1, true, &socket_factory).make_request(req);

        BOOST_CHECK_EQUAL(200, resp.status.code);
        BOOST_CHECK_EQUAL("OK", resp.body);
    }
    {
        // Expected to fail since cant validate the certificate
        http::Request req;
        req.method = GET;
        req.headers.add("Host", "localhost");
        req.raw_url = "/index.html";
        BOOST_CHECK_THROW(
            http::Client("localhost", BASE_PORT + 2, true, &socket_factory).make_request(req),
            CertificateVerificationError);
    }
    server.exit();
    server_thread.join();
}

BOOST_AUTO_TEST_CASE(keep_alive)
{
    TestThread server_thread;
    Server server;
    server.add_tcp_listener("127.0.0.1", BASE_PORT + 3);

    server_thread = TestThread(std::bind(&Server::run, &server));

    {
        ClientConnection conn(std::make_unique<TcpSocket>("localhost", BASE_PORT + 3));
        Request req;
        req.method = GET;
        req.headers.add("Host", "localhost");
        req.headers.add("Connection", "close");
        req.raw_url = "/index.html";

        auto resp = conn.make_request(req);
        BOOST_CHECK_EQUAL("close", resp.headers.get("Connection"));

        BOOST_CHECK_THROW(conn.make_request(req), std::runtime_error);
    }

    {
        ClientConnection conn(std::make_unique<TcpSocket>("localhost", BASE_PORT + 3));
        Request req;
        req.method = GET;
        req.headers.add("Host", "localhost");
        req.headers.add("Connection", "keep-alive");
        req.raw_url = "/index.html";

        auto resp = conn.make_request(req);
        BOOST_CHECK_EQUAL("keep-alive", resp.headers.get("Connection"));

        BOOST_CHECK_NO_THROW(conn.make_request(req));
    }

    server.exit();
    server_thread.join();
}
BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Remove std::make_unique as is C++14<commit_after>#include <boost/test/unit_test.hpp>
#include "client/Client.hpp"
#include "client/SocketFactory.hpp"
#include "server/CoreServer.hpp"
#include "net/Cert.hpp"
#include "net/Net.hpp"
#include "net/TcpSocket.hpp"
#include "Response.hpp"
#include "../TestThread.hpp"
#include <thread>

using namespace http;

BOOST_AUTO_TEST_SUITE(TestCoreServer)

static const uint16_t BASE_PORT = 5100;

class Server : public http::CoreServer
{
protected:
    virtual http::Response handle_request(http::Request &)override
    {
        http::Response resp;
        resp.status_code(200);
        resp.headers.add("Content-Type", "text/plain");
        resp.body = "OK";
        return resp;
    }
    virtual http::Response parser_error_page(const http::ParserError &)override
    {
        throw std::runtime_error("Unexpected parser_error_page");
    }
};

void success_server_thread(Server *server)
{
    server->run();
}
BOOST_AUTO_TEST_CASE(success)
{
    TestThread server_thread;
    Server server;
    server.add_tcp_listener("127.0.0.1", BASE_PORT + 0);
    server.add_tls_listener("127.0.0.1", BASE_PORT + 1, load_pfx_cert("localhost.pfx", "password"));
    server.add_tls_listener("127.0.0.1", BASE_PORT + 2, load_pfx_cert("wrong-host.pfx", "password"));

    server_thread = TestThread(std::bind(&Server::run, &server));

    http::DefaultSocketFactory socket_factory;

    {
        // http://
        http::Request req;
        req.method = GET;
        req.headers.add("Host", "localhost");
        req.raw_url = "/index.html";

        auto resp = http::Client("localhost", BASE_PORT + 0, false, &socket_factory).make_request(req);

        BOOST_CHECK_EQUAL(200, resp.status.code);
        BOOST_CHECK_EQUAL("OK", resp.body);
    }
    {
        // https:// - TLS
        http::Request req;
        req.method = GET;
        req.headers.add("Host", "localhost");
        req.raw_url = "/index.html";

        auto resp = http::Client("localhost", BASE_PORT + 1, true, &socket_factory).make_request(req);

        BOOST_CHECK_EQUAL(200, resp.status.code);
        BOOST_CHECK_EQUAL("OK", resp.body);
    }
    {
        // Expected to fail since cant validate the certificate
        http::Request req;
        req.method = GET;
        req.headers.add("Host", "localhost");
        req.raw_url = "/index.html";
        BOOST_CHECK_THROW(
            http::Client("localhost", BASE_PORT + 2, true, &socket_factory).make_request(req),
            CertificateVerificationError);
    }
    server.exit();
    server_thread.join();
}

BOOST_AUTO_TEST_CASE(keep_alive)
{
    TestThread server_thread;
    Server server;
    server.add_tcp_listener("127.0.0.1", BASE_PORT + 3);

    server_thread = TestThread(std::bind(&Server::run, &server));

    {
        ClientConnection conn(std::unique_ptr<Socket>(new TcpSocket("localhost", BASE_PORT + 3)));
        Request req;
        req.method = GET;
        req.headers.add("Host", "localhost");
        req.headers.add("Connection", "close");
        req.raw_url = "/index.html";

        auto resp = conn.make_request(req);
        BOOST_CHECK_EQUAL("close", resp.headers.get("Connection"));

        BOOST_CHECK_THROW(conn.make_request(req), std::runtime_error);
    }

    {
        ClientConnection conn(std::unique_ptr<Socket>(new TcpSocket("localhost", BASE_PORT + 3)));
        Request req;
        req.method = GET;
        req.headers.add("Host", "localhost");
        req.headers.add("Connection", "keep-alive");
        req.raw_url = "/index.html";

        auto resp = conn.make_request(req);
        BOOST_CHECK_EQUAL("keep-alive", resp.headers.get("Connection"));

        BOOST_CHECK_NO_THROW(conn.make_request(req));
    }

    server.exit();
    server_thread.join();
}
BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#include "himan_unit.h"
#include "util.h"

#define BOOST_TEST_MODULE util

using namespace std;
using namespace himan;

const double kEpsilon = 1e-3;

BOOST_AUTO_TEST_CASE(UV_TO_GEOGRAPHICAL)
{
	// Transform grid coordinates to lat and lon in stereographic projection

	himan::point stereoUV(8.484046, 3.804569);
	double lon = 72.79;

	himan::point latlon = util::UVToGeographical(lon, stereoUV);

	BOOST_CHECK_CLOSE(latlon.X(), 6.144442, kEpsilon);
	BOOST_CHECK_CLOSE(latlon.Y(), -6.978511, kEpsilon);

	stereoUV.X(-0.2453410);
	stereoUV.Y(0.5808838);
	lon = 23.39;

	latlon = util::UVToGeographical(lon, stereoUV);

	BOOST_CHECK_CLOSE(latlon.X(), 5.4238806e-03, kEpsilon);
	BOOST_CHECK_CLOSE(latlon.Y(), 0.6305464, kEpsilon);

}

BOOST_AUTO_TEST_CASE(FILTER2D)
{
	// Filter a plane with given filter kernel
	// Declare matrices
	himan::matrix<double> A(11,8,1,kFloatMissing);
	himan::matrix<double> B(3,3,1,kFloatMissing);
	himan::matrix<double> C;
	himan::matrix<double> D(11,8,1,kFloatMissing);

	// Fill matrix A that will be smoothend with checker-board pattern
	for(size_t i=0; i < A.Size(); ++i)
	{
		if(i % 2 == 0)
      		{
			A.Set(i, 0);
      		}
      		else
      		{
			A.Set(i, 36);
      		}

	}

	// Fill matrix D with solution of the smoothened matrix Filter2D(A,B)
	for(size_t i=0; i < D.SizeX(); ++i)
	{
		for(size_t j=0; j < D.SizeY(); ++j)
		{
			if(i == 0 || i == A.SizeX()-1 || j == 0 || j == A.SizeY()-1)
			{
				D.Set(i,j,0,18);
			}
			else if ((i % 2 != 0 && j % 2 != 0) || (i % 2 == 0 && j % 2 == 0))
			{
				D.Set(i,j,0,16);
			}
			else
			{
				D.Set(i,j,0,20);
			}
		}
	}

	// Fill matrix B (filter kernel) with constant values 1/9 so that sum(B) == 1
	double filter_coeff(1.0/9.0);
	B.Fill(filter_coeff);

	// Compute smoothened matrix
	C = himan::util::Filter2D(A,B);

	// Compare results
	for(size_t i=0; i < C.Size(); ++i)
	{
		BOOST_CHECK_CLOSE(C.At(i),D.At(i),kEpsilon);
	}

	// computed filtered matrix
	std::cout << "Matrix C computed with Filter2D:" << std::endl;
	for (size_t i=0; i < C.SizeX();++i){
    		for (size_t j=0; j < C.SizeY();++j){
      			std::cout << C.At(i,j,0) << " ";
    		}
    		std::cout << std::endl;
  	}

	std::cout << std::endl << "Matrix D as reference case for Filter2D computation:" << std::endl;

	for (size_t i=0; i < D.SizeX();++i){
    		for (size_t j=0; j < D.SizeY();++j){
      			std::cout << D.At(i,j,0) << " ";
    		}
    		std::cout << std::endl;
  	}

}
BOOST_AUTO_TEST_CASE(CENTRAL_DIFFERENCE)
{
    // Filter a plane with given filter kernel
    // Declare matrices
    himan::matrix<double> A(5,5,1,kFloatMissing);
    himan::matrix<double> B;
	himan::matrix<double> C;

	// Matrices containing the correct solution
	himan::matrix<double> D(5,5,1,kFloatMissing);
	himan::matrix<double> E(5,5,1,kFloatMissing);

    // Fill matrix A and solution matrices D and E
    for(size_t i=0; i < A.Size(); ++i)
    {
        A.Set(i, double(i));
		D.Set(i,1.0/double(1+i/5));
		E.Set(i,5.0);
    }

	std::pair<himan::matrix<double>,himan::matrix<double>> grad_A;

	// Declare vectors for grid spacing
	std::vector<double> dx {1.0,2.0,3.0,4.0,5.0};
	std::vector<double> dy(5,1.0);

	grad_A = himan::util::CentralDifference(A,dx,dy);
	B = std::get<0>(grad_A);
	C = std::get<1>(grad_A);

	assert(B==D && C==E);

}

BOOST_AUTO_TEST_CASE(MAKESQLINTERVAL)
{

	forecast_time f1("2015-01-09 00:00:00", "2015-01-09 12:00:00");

	BOOST_REQUIRE(util::MakeSQLInterval(f1) == "12:00:00");

	f1.StepResolution(kMinuteResolution);

	BOOST_REQUIRE(util::MakeSQLInterval(f1) == "12:00:00");

	forecast_time f2("2015-01-09 00:00:00", "2015-01-09 00:15:00");

	BOOST_REQUIRE(util::MakeSQLInterval(f2) == "00:00:00");

	f2.StepResolution(kMinuteResolution);

	BOOST_REQUIRE(util::MakeSQLInterval(f2) == "00:15:00");

	forecast_time f3("2015-01-09 00:00:00", "2015-01-19 00:16:00");

	BOOST_REQUIRE(util::MakeSQLInterval(f3) == "240:00:00");

	forecast_time f4("2015-01-09 00:00:00", "2015-10-19 00:00:00");

	BOOST_REQUIRE(util::MakeSQLInterval(f4) == "6792:00:00");

	forecast_time f5("2015-01-09 00:00:00", "2015-01-09 00:00:00");

	BOOST_REQUIRE(util::MakeSQLInterval(f5) == "00:00:00");
}

BOOST_AUTO_TEST_CASE(EXPAND)
{
	setenv("BOOST_TEST", "xyz", 1);

	string test = "$BOOST_TEST/asdf";

	string expanded = util::Expand(test);

	BOOST_REQUIRE(expanded == "xyz/asdf");

	setenv("BOOST_TEST_2", "123", 1);

	test = "$BOOST_TEST/asdf/$BOOST_TEST_2";

	expanded = util::Expand(test);

	BOOST_REQUIRE(expanded == "xyz/asdf/123");

}
<commit_msg>use BOOST_CHECK<commit_after>#include "himan_unit.h"
#include "util.h"

#define BOOST_TEST_MODULE util

using namespace std;
using namespace himan;

const double kEpsilon = 1e-3;

BOOST_AUTO_TEST_CASE(UV_TO_GEOGRAPHICAL)
{
	// Transform grid coordinates to lat and lon in stereographic projection

	himan::point stereoUV(8.484046, 3.804569);
	double lon = 72.79;

	himan::point latlon = util::UVToGeographical(lon, stereoUV);

	BOOST_CHECK_CLOSE(latlon.X(), 6.144442, kEpsilon);
	BOOST_CHECK_CLOSE(latlon.Y(), -6.978511, kEpsilon);

	stereoUV.X(-0.2453410);
	stereoUV.Y(0.5808838);
	lon = 23.39;

	latlon = util::UVToGeographical(lon, stereoUV);

	BOOST_CHECK_CLOSE(latlon.X(), 5.4238806e-03, kEpsilon);
	BOOST_CHECK_CLOSE(latlon.Y(), 0.6305464, kEpsilon);

}

BOOST_AUTO_TEST_CASE(FILTER2D)
{
	// Filter a plane with given filter kernel
	// Declare matrices
	himan::matrix<double> A(11,8,1,kFloatMissing);
	himan::matrix<double> B(3,3,1,kFloatMissing);
	himan::matrix<double> C;
	himan::matrix<double> D(11,8,1,kFloatMissing);

	// Fill matrix A that will be smoothend with checker-board pattern
	for(size_t i=0; i < A.Size(); ++i)
	{
		if(i % 2 == 0)
      		{
			A.Set(i, 0);
      		}
      		else
      		{
			A.Set(i, 36);
      		}

	}

	// Fill matrix D with solution of the smoothened matrix Filter2D(A,B)
	for(size_t i=0; i < D.SizeX(); ++i)
	{
		for(size_t j=0; j < D.SizeY(); ++j)
		{
			if(i == 0 || i == A.SizeX()-1 || j == 0 || j == A.SizeY()-1)
			{
				D.Set(i,j,0,18);
			}
			else if ((i % 2 != 0 && j % 2 != 0) || (i % 2 == 0 && j % 2 == 0))
			{
				D.Set(i,j,0,16);
			}
			else
			{
				D.Set(i,j,0,20);
			}
		}
	}

	// Fill matrix B (filter kernel) with constant values 1/9 so that sum(B) == 1
	double filter_coeff(1.0/9.0);
	B.Fill(filter_coeff);

	// Compute smoothened matrix
	C = himan::util::Filter2D(A,B);

	// Compare results
	for(size_t i=0; i < C.Size(); ++i)
	{
		BOOST_CHECK_CLOSE(C.At(i),D.At(i),kEpsilon);
	}

	// computed filtered matrix
	std::cout << "Matrix C computed with Filter2D:" << std::endl;
	for (size_t i=0; i < C.SizeX();++i){
    		for (size_t j=0; j < C.SizeY();++j){
      			std::cout << C.At(i,j,0) << " ";
    		}
    		std::cout << std::endl;
  	}

	std::cout << std::endl << "Matrix D as reference case for Filter2D computation:" << std::endl;

	for (size_t i=0; i < D.SizeX();++i){
    		for (size_t j=0; j < D.SizeY();++j){
      			std::cout << D.At(i,j,0) << " ";
    		}
    		std::cout << std::endl;
  	}

}
BOOST_AUTO_TEST_CASE(CENTRAL_DIFFERENCE)
{
    // Filter a plane with given filter kernel
    // Declare matrices
    himan::matrix<double> A(5,5,1,kFloatMissing);
    himan::matrix<double> B;
	himan::matrix<double> C;

	// Matrices containing the correct solution
	himan::matrix<double> D(5,5,1,kFloatMissing);
	himan::matrix<double> E(5,5,1,kFloatMissing);

    // Fill matrix A and solution matrices D and E
    for(size_t i=0; i < A.Size(); ++i)
    {
        A.Set(i, double(i));
		D.Set(i,1.0/double(1+i/5));
		E.Set(i,5.0);
    }

	std::pair<himan::matrix<double>,himan::matrix<double>> grad_A;

	// Declare vectors for grid spacing
	std::vector<double> dx {1.0,2.0,3.0,4.0,5.0};
	std::vector<double> dy(5,1.0);

	grad_A = himan::util::CentralDifference(A,dx,dy);
	B = std::get<0>(grad_A);
	C = std::get<1>(grad_A);

	BOOST_CHECK(B==D && C==E);

}

BOOST_AUTO_TEST_CASE(MAKESQLINTERVAL)
{

	forecast_time f1("2015-01-09 00:00:00", "2015-01-09 12:00:00");

	BOOST_REQUIRE(util::MakeSQLInterval(f1) == "12:00:00");

	f1.StepResolution(kMinuteResolution);

	BOOST_REQUIRE(util::MakeSQLInterval(f1) == "12:00:00");

	forecast_time f2("2015-01-09 00:00:00", "2015-01-09 00:15:00");

	BOOST_REQUIRE(util::MakeSQLInterval(f2) == "00:00:00");

	f2.StepResolution(kMinuteResolution);

	BOOST_REQUIRE(util::MakeSQLInterval(f2) == "00:15:00");

	forecast_time f3("2015-01-09 00:00:00", "2015-01-19 00:16:00");

	BOOST_REQUIRE(util::MakeSQLInterval(f3) == "240:00:00");

	forecast_time f4("2015-01-09 00:00:00", "2015-10-19 00:00:00");

	BOOST_REQUIRE(util::MakeSQLInterval(f4) == "6792:00:00");

	forecast_time f5("2015-01-09 00:00:00", "2015-01-09 00:00:00");

	BOOST_REQUIRE(util::MakeSQLInterval(f5) == "00:00:00");
}

BOOST_AUTO_TEST_CASE(EXPAND)
{
	setenv("BOOST_TEST", "xyz", 1);

	string test = "$BOOST_TEST/asdf";

	string expanded = util::Expand(test);

	BOOST_REQUIRE(expanded == "xyz/asdf");

	setenv("BOOST_TEST_2", "123", 1);

	test = "$BOOST_TEST/asdf/$BOOST_TEST_2";

	expanded = util::Expand(test);

	BOOST_REQUIRE(expanded == "xyz/asdf/123");

}
<|endoftext|>