<commit_before>/// A little LOGger

#pragma once

#include <ostream>
#include <string>
#include <cassert>
#include <cstdlib>
#include <pthread.h>

namespace hf {

/// C++14 later
/// Linux

inline std::string now_timestamp()
{
  return "[1999-06-06T06:06:06.666]";
}

class alog /* final */ {
public:
  enum level_t {
    UNDER_LVL = 0,
    VERBOSE,
    DEBUG,
    INFO,
    WARNING,
    ERROR,
    SILENT,
    OVER_LVL
  };

  static alog& get_instance()
  {
    return get_instance(nullptr);
  }
  static alog& get_instance(std::ostream& ost)
  {
    return get_instance(&ost);
  }

  bool operator==(const alog& rhs) const
  {
    return &rhs == this || (rhs.level_ == level_ && rhs.ost_ == ost_);
  }
  bool operator!=(const alog& rhs) const
  {
    return (rhs.level_ != level_ || rhs.ost_ != ost_);
  }

  // for test
  std::ostream& t()
  {
    return (*this)() << "[TEST]";
  }
  // for verbose
  std::ostream& v()
  {
    return (*this)(VERBOSE) << "[V]";
  }
  // for debug
  std::ostream& d()
  {
    return (*this)(DEBUG) << "[D]";
  }
  // for info
  std::ostream& i()
  {
    return (*this)(INFO) << "[I]";
  }
  // for warning
  std::ostream& w()
  {
    return (*this)(WARNING) << "[W]";
  }
  // for error
  std::ostream& e()
  {
    return (*this)(ERROR) << "[E]";
  }
  // ログレベル設定が何であっても強制的に出力する
  std::ostream& force()
  {
    return (*this)();
  }

  template<typename T> friend std::ostream& operator<<(alog& log, const T& rhs);

  alog& level(level_t lvl)
  {
    assert(UNDER_LVL < lvl && lvl < OVER_LVL);
    if (lvl <= UNDER_LVL || OVER_LVL <= lvl) {
      abort();
    }

    level_ = lvl;
    return *this;
  }
  level_t level()
  {
    return level_;
  }

private:
  alog() = default;
  alog& operator=(const alog&) = delete;

  std::ostream& operator()()
  {
    return (*this) << now_timestamp() << "[thd:" << pthread_self() << "] ";
  }
  std::ostream& operator()(level_t lvl)
  {
    if (lvl >= level_) {
      return (*this) << now_timestamp() << "[thd:" << pthread_self() << "] ";
    }
    else {
      return null_ost_;
    }
  }

  static alog& get_instance(std::ostream* ost)
  {
    static alog log;
    if (ost != nullptr) {
      log.ost_ = ost;
    }
    return log;
  }

  std::ostream null_ost_{nullptr}; // 何も出力しない ostream用
  level_t level_ = level_t::SILENT;
  std::ostream* ost_ = &null_ost_;
};

template<typename T> std::ostream& operator<<(alog& log, const T& rhs)
{
  return (*log.ost_) << rhs;
}

} // namespace hf
<commit_msg>pthread_self() -> std::this_thread::get_id()<commit_after>/// A little LOGger

#pragma once

#include <ostream>
#include <string>
#include <thread>

#include <cassert>
#include <cstdlib>

namespace hf {

/// C++14 later
/// Linux

inline std::string now_timestamp()
{
  return "[1999-06-06T06:06:06.666]";
}

class alog final {
public:
  enum level_t {
    UNDER_LVL = 0,
    VERBOSE,
    DEBUG,
    INFO,
    WARNING,
    ERROR,
    SILENT,
    OVER_LVL
  };

  static alog& get_instance()
  {
    return get_instance(nullptr);
  }
  static alog& get_instance(std::ostream& ost)
  {
    return get_instance(&ost);
  }

  bool operator==(const alog& rhs) const
  {
    return &rhs == this || (rhs.level_ == level_ && rhs.ost_ == ost_);
  }
  bool operator!=(const alog& rhs) const
  {
    return (rhs.level_ != level_ || rhs.ost_ != ost_);
  }

  // for test
  std::ostream& t()
  {
    return (*this)() << "[TEST]";
  }
  // for verbose
  std::ostream& v()
  {
    return (*this)(VERBOSE) << "[V]";
  }
  // for debug
  std::ostream& d()
  {
    return (*this)(DEBUG) << "[D]";
  }
  // for info
  std::ostream& i()
  {
    return (*this)(INFO) << "[I]";
  }
  // for warning
  std::ostream& w()
  {
    return (*this)(WARNING) << "[W]";
  }
  // for error
  std::ostream& e()
  {
    return (*this)(ERROR) << "[E]";
  }
  // ログレベル設定が何であっても強制的に出力する
  std::ostream& force()
  {
    return (*this)();
  }

  template<typename T> friend std::ostream& operator<<(alog& log, const T& rhs);

  alog& level(level_t lvl)
  {
    assert(UNDER_LVL < lvl && lvl < OVER_LVL);
    if (lvl <= UNDER_LVL || OVER_LVL <= lvl) {
      abort();
    }

    level_ = lvl;
    return *this;
  }
  level_t level()
  {
    return level_;
  }

private:
  alog() = default;
  alog& operator=(const alog&) = delete;

  std::ostream& operator()()
  {
    return (*this) << now_timestamp() << "[thd:" << std::this_thread::get_id() << "] ";
  }
  std::ostream& operator()(level_t lvl)
  {
    if (lvl >= level_) {
      return (*this) << now_timestamp() << "[thd:" << std::this_thread::get_id() << "] ";
    }
    else {
      return null_ost_;
    }
  }

  static alog& get_instance(std::ostream* ost)
  {
    static alog log;
    if (ost != nullptr) {
      log.ost_ = ost;
    }
    return log;
  }

  std::ostream null_ost_{nullptr}; // 何も出力しない ostream用
  level_t level_ = level_t::SILENT;
  std::ostream* ost_ = &null_ost_;
};

template<typename T> std::ostream& operator<<(alog& log, const T& rhs)
{
  return (*log.ost_) << rhs;
}

} // namespace hf
<|endoftext|>


<commit_before>#ifndef DOUBLE_HPP
#define DOUBLE_HPP

#include <cmath>
#include <type_traits>

template<typename FType=double, typename std::enable_if<std::is_floating_point<FType>::value, std::nullptr_t>::type = nullptr>
static inline constexpr double
geteps(int prec=9)
{
  return std::pow(static_cast<FType>(1.0), -prec - 1);
}

template<int PRECISION=9, typename FType=double, typename std::enable_if<std::is_floating_point<FType>::value, std::nullptr_t>::type = nullptr>
static inline bool
eq(FType a, FType b)
{
  constexpr FType eps = geteps<FType>(PRECISION);
  return std::abs(a - b) < eps;
}

template<int PRECISION=9, typename FType=double, typename std::enable_if<std::is_floating_point<FType>::value, std::nullptr_t>::type = nullptr>
static inline bool
neq(FType a, FType b)
{
  constexpr FType eps = geteps<FType>(PRECISION);
  return std::abs(a - b) >= eps;
}

template<int PRECISION=9, typename FType=double, typename std::enable_if<std::is_floating_point<FType>::value, std::nullptr_t>::type = nullptr>
static inline bool
lt(FType a, FType b)
{
  constexpr FType eps = geteps<FType>(PRECISION);
  return a < b - eps;
}

template<int PRECISION=9, typename FType=double, typename std::enable_if<std::is_floating_point<FType>::value, std::nullptr_t>::type = nullptr>
static inline bool
leq(FType a, FType b)
{
  constexpr FType eps = geteps<FType>(PRECISION);
  return a < b + eps;
}

template<int PRECISION=9, typename FType=double, typename std::enable_if<std::is_floating_point<FType>::value, std::nullptr_t>::type = nullptr>
static inline bool
gt(FType a, FType b)
{
  constexpr FType eps = geteps<FType>(PRECISION);
  return a > b - eps;
}

template<int PRECISION=9, typename FType=double, typename std::enable_if<std::is_floating_point<FType>::value, std::nullptr_t>::type = nullptr>
static inline bool
geq(FType a, FType b)
{
  constexpr FType eps = geteps<FType>(PRECISION);
  return a > b + eps;
}

template<int PRECISION=9, typename FType=double, typename std::enable_if<std::is_floating_point<FType>::value, std::nullptr_t>::type = nullptr>
static inline bool
isin(FType x, FType a, FType b)
{
  return geq(x, a) && leq(x, b);
}

#endif  // DOUBLE_HPP
<commit_msg>Fix name of type parameter of template<commit_after>/*!
 * @file Double.hpp
 * @brief Utility functions about floating point
 * @author koturn
 */
#ifndef DOUBLE_HPP
#define DOUBLE_HPP

#include <cmath>
#include <type_traits>

template<typename T = double>
static inline constexpr double
geteps(int prec = 9)
{
  static_assert(std::is_floating_point<T>::value, "[geteps] T must be a floating point type");

  return std::pow(static_cast<T>(1.0), -prec - 1);
}

template<
  int kPrecision = 9,
  typename T = double
>
static inline bool
eq(T a, T b)
{
  static_assert(std::is_floating_point<T>::value, "[eq] T must be a floating point type");

  constexpr T eps = geteps<T>(kPrecision);
  return std::abs(a - b) < eps;
}

template<
  int kPrecision = 9,
  typename T = double
>
static inline bool
neq(T a, T b)
{
  static_assert(std::is_floating_point<T>::value, "[neq] T must be a floating point type");

  constexpr T eps = geteps<T>(kPrecision);
  return std::abs(a - b) >= eps;
}

template<
  int kPrecision = 9,
  typename T = double
>
static inline bool
lt(T a, T b)
{
  static_assert(std::is_floating_point<T>::value, "[lt] T must be a floating point type");

  constexpr T eps = geteps<T>(kPrecision);
  return a < b - eps;
}

template<
  int kPrecision = 9,
  typename T = double
>
static inline bool
leq(T a, T b)
{
  static_assert(std::is_floating_point<T>::value, "[lt] T must be a floating point type");

  constexpr T eps = geteps<T>(kPrecision);
  return a < b + eps;
}

template<
  int kPrecision = 9,
  typename T = double
>
static inline bool
gt(T a, T b)
{
  static_assert(std::is_floating_point<T>::value, "[gt] T must be a floating point type");

  constexpr T eps = geteps<T>(kPrecision);
  return a > b - eps;
}

template<
  int kPrecision = 9,
  typename T = double
>
static inline bool
geq(T a, T b)
{
  static_assert(std::is_floating_point<T>::value, "[geq] T must be a floating point type");

  constexpr T eps = geteps<T>(kPrecision);
  return a > b + eps;
}

template<
  int kPrecision = 9,
  typename T = double
>
static inline bool
isin(T x, T a, T b)
{
  static_assert(std::is_floating_point<T>::value, "[isin] T must be a floating point type");

  return geq(x, a) && leq(x, b);
}

#endif  // DOUBLE_HPP
<|endoftext|>


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

#ifndef BBOX_HH
#define BBOX_HH

#include <glosm/Math.hh>

/**
 * Template axis-aligned bounding box class
 */
template <typename T>
struct BBox {
	enum Side {
		NONE = 0,
		LEFT = 1,
		BOTTOM = 2,
		RIGHT = 3,
		TOP = 4
	};

	typedef typename LongType<T>::type LT;

	/* ctors */
	BBox(const Vector2<T>& one, const Vector2<T>& two) {
		if (one.x < two.x) {
			left = one.x;
			right = two.x;
		} else {
			left = two.x;
			right = one.x;
		}

		if (one.y < two.y) {
			bottom = one.y;
			top = two.y;
		} else {
			bottom = two.y;
			top = one.y;
		}
	}

	BBox(T l, T b, T r, T t): left(l), bottom(b), right(r), top(t) {
	}

	BBox(const BBox<T>& b): left(b.left), bottom(b.bottom), right(b.right), top(b.top) {
	}

	/* static `ctors' */
	static BBox<T> Full() {
		return BBox<T>(std::numeric_limits<T>::min(), std::numeric_limits<T>::min(), std::numeric_limits<T>::max(), std::numeric_limits<T>::max());
	}

	static BBox<T> Empty() {
		return BBox<T>(std::numeric_limits<T>::max(), std::numeric_limits<T>::max(), std::numeric_limits<T>::min(), std::numeric_limits<T>::min());
	}

	/* specialized only for <osmint_t>, see BBox.cc */
	static BBox<T> ForEarth();
	static BBox<T> ForMercatorTile(int zoom, int x, int y);
	static BBox<T> ForGeoTile(int zoom, int x, int y);

	/* operators - may be added later if needed: addition/substraction/intersection */

	/* modifiers */
	void Include(const Vector2<T>& point) {
		if (point.x < left)
			left = point.x;
		if (point.x > right)
			right = point.x;
		if (point.y < bottom)
			bottom = point.y;
		if (point.y > top)
			top = point.y;
	}

	void Include(const BBox<T>& bbox) {
		if (bbox.left < left)
			left = bbox.left;
		if (bbox.right > right)
			right = bbox.right;
		if (bbox.bottom < bottom)
			bottom = bbox.bottom;
		if (bbox.top > top)
			top = bbox.top;
	}

	/* derivs */
	Vector2<T> GetCenter() const {
		return Vector2<T>(((LT)left + (LT)right)/2, ((LT)top + (LT)bottom)/2);
	}

	Vector2<T> GetBottomLeft() const {
		return Vector2<T>(left, bottom);
	}

	Vector2<T> GetBottomRight() const {
		return Vector2<T>(right, bottom);
	}

	Vector2<T> GetTopLeft() const {
		return Vector2<T>(left, top);
	}

	Vector2<T> GetTopRight() const {
		return Vector2<T>(right, top);
	}

	/* tests */
	bool IsEmpty() const {
		return left > right || bottom > top;
	}

	bool Contains(const Vector2<T>& v) const {
		return v.x >= left && v.x <= right && v.y >= bottom && v.y <= top;
	}

	bool Intersects(const BBox<T>& bbox) const {
		return !(bbox.right < left || bbox.left > right || bbox.top < bottom || bbox.bottom > top);
	}

	/* data */
	T left, bottom, right, top;
};

typedef BBox<osmint_t> BBoxi;
typedef BBox<osmlong_t> BBoxl;
typedef BBox<float> BBoxf;
typedef BBox<double> BBoxd;

#endif
<commit_msg>Add method<commit_after>/*
 * Copyright (C) 2010-2011 Dmitry Marakasov
 *
 * This file is part of glosm.
 *
 * glosm is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * glosm is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with glosm.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef BBOX_HH
#define BBOX_HH

#include <glosm/Math.hh>

/**
 * Template axis-aligned bounding box class
 */
template <typename T>
struct BBox {
	enum Side {
		NONE = 0,
		LEFT = 1,
		BOTTOM = 2,
		RIGHT = 3,
		TOP = 4
	};

	typedef typename LongType<T>::type LT;

	/* ctors */
	BBox(const Vector2<T>& one, const Vector2<T>& two) {
		if (one.x < two.x) {
			left = one.x;
			right = two.x;
		} else {
			left = two.x;
			right = one.x;
		}

		if (one.y < two.y) {
			bottom = one.y;
			top = two.y;
		} else {
			bottom = two.y;
			top = one.y;
		}
	}

	BBox(T l, T b, T r, T t): left(l), bottom(b), right(r), top(t) {
	}

	BBox(const BBox<T>& b): left(b.left), bottom(b.bottom), right(b.right), top(b.top) {
	}

	/* static `ctors' */
	static BBox<T> Full() {
		return BBox<T>(std::numeric_limits<T>::min(), std::numeric_limits<T>::min(), std::numeric_limits<T>::max(), std::numeric_limits<T>::max());
	}

	static BBox<T> Empty() {
		return BBox<T>(std::numeric_limits<T>::max(), std::numeric_limits<T>::max(), std::numeric_limits<T>::min(), std::numeric_limits<T>::min());
	}

	/* specialized only for <osmint_t>, see BBox.cc */
	static BBox<T> ForEarth();
	static BBox<T> ForMercatorTile(int zoom, int x, int y);
	static BBox<T> ForGeoTile(int zoom, int x, int y);

	/* operators - may be added later if needed: addition/substraction/intersection */

	/* modifiers */
	void Include(const Vector2<T>& point) {
		if (point.x < left)
			left = point.x;
		if (point.x > right)
			right = point.x;
		if (point.y < bottom)
			bottom = point.y;
		if (point.y > top)
			top = point.y;
	}

	void Include(const BBox<T>& bbox) {
		if (bbox.left < left)
			left = bbox.left;
		if (bbox.right > right)
			right = bbox.right;
		if (bbox.bottom < bottom)
			bottom = bbox.bottom;
		if (bbox.top > top)
			top = bbox.top;
	}

	/* derivs */
	Vector2<T> GetCenter() const {
		return Vector2<T>(((LT)left + (LT)right)/2, ((LT)top + (LT)bottom)/2);
	}

	Vector2<T> GetBottomLeft() const {
		return Vector2<T>(left, bottom);
	}

	Vector2<T> GetBottomRight() const {
		return Vector2<T>(right, bottom);
	}

	Vector2<T> GetTopLeft() const {
		return Vector2<T>(left, top);
	}

	Vector2<T> GetTopRight() const {
		return Vector2<T>(right, top);
	}

	/* tests */
	bool IsEmpty() const {
		return left > right || bottom > top;
	}

	bool Contains(const Vector2<T>& v) const {
		return v.x >= left && v.x <= right && v.y >= bottom && v.y <= top;
	}

	bool Intersects(const BBox<T>& bbox) const {
		return !(bbox.right < left || bbox.left > right || bbox.top < bottom || bbox.bottom > top);
	}

	bool IsPointOutAtSide(const Vector2i& p, Side s) const {
		switch (s) {
		case LEFT: return p.x < left;
		case RIGHT: return p.x > right;
		case TOP: return p.y > top;
		case BOTTOM: return p.y < bottom;
		default: return false;
		}
	}

	/* data */
	T left, bottom, right, top;
};

typedef BBox<osmint_t> BBoxi;
typedef BBox<osmlong_t> BBoxl;
typedef BBox<float> BBoxf;
typedef BBox<double> BBoxd;

#endif
<|endoftext|>


<commit_before>/*
    Copyright (c) 2006 Volker Krause <volker.krause@rwth-aachen.de>

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

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "kmime_content_test.h"
#include <qtest_kde.h>

#include <kmime_content.h>
#include <kmime_message.h>
#include <kmime_headers.h>
using namespace KMime;

QTEST_KDEMAIN( KMimeContentTest, NoGUI )

void KMimeContentTest::testGetHeaderInstance( )
{
  // getHeaderInstance() is protected, so we need to test it via KMime::Message
  Message *c = new Message();
  Headers::From *from;
  Headers::From *f1 = c->from( true );
  Headers::From *f2 = c->from( true );
  QCOMPARE( f1, f2 );
  delete c;
}

#include "kmime_content_test.moc"
<commit_msg>Test that shows the reason for the strange kmime behaviour.<commit_after>/*
    Copyright (c) 2006 Volker Krause <volker.krause@rwth-aachen.de>

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

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

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "kmime_content_test.h"
#include <qtest_kde.h>

#include <kmime_content.h>
#include <kmime_headers.h>
#include <kmime_message.h>
#include <kmime_headers.h>
using namespace KMime;

QTEST_KDEMAIN( KMimeContentTest, NoGUI )

void KMimeContentTest::testGetHeaderInstance( )
{
  // this fails with libkmime4...
  Headers::From *myfrom = new Headers::From();
  QCOMPARE( myfrom->type(), "From" );
  Headers::Base *mybase = myfrom;
  QCOMPARE( mybase->type(), "From" );

  // getHeaderInstance() is protected, so we need to test it via KMime::Message
  Message *c = new Message();
  Headers::From *from;
  Headers::From *f1 = c->from( true );
  Headers::From *f2 = c->from( true );
  QCOMPARE( f1, f2 );
  delete c;
}

#include "kmime_content_test.moc"
<|endoftext|>


<commit_before>#include "broker_dslink_util.h"

using BrokerDsLinkTest = SetUpBase;

TEST_F(BrokerDsLinkTest, ClientRemoveTest) {
  Storage::get_config_bucket().remove_all();

  // First Create Broker
  auto app = make_shared_<App>();
  auto broker = broker_dslink_test::create_broker(app);
  broker->run();
  ASYNC_EXPECT_TRUE(1000, *broker->strand,
                    [&]() { return broker->get_active_server_port() != 0; });
  int32_t port;

  switch (protocol()) {
    case dsa::ProtocolType::PROT_DSS:
      port = broker->get_active_secure_port();
      break;
    default:
      port = broker->get_active_server_port();
  }

  EXPECT_TRUE(port != 0);

  auto link_1 =
      broker_dslink_test::create_dslink(app, port, "Test1", false, protocol());
  auto link_2 =
      broker_dslink_test::create_dslink(app, port, "Test2", true, protocol());

  int downstream_listed = 0, clients_listed = 0;
  bool link1_connected = false, allow_all_set = false;
  link_1->connect([&](const shared_ptr_<Connection> connection,
                      ref_<DsLinkRequester> link_req) {
    link1_connected = true;

    // set request to change value
    auto set_request = make_ref_<SetRequestMessage>();
    set_request->set_value(Var(false));
    set_request->set_target_path("Sys/Clients/Allow_All");

    // send set request
    link_req->set(
        [&, link_req](IncomingSetStream &stream,
                      ref_<const SetResponseMessage> &&msg) {
          EXPECT_TRUE(msg->get_status() == Status::OK ||
                      msg->get_status() == Status::DONE);
          allow_all_set = true;

          link_req->list("Downstream", [&, link_req](
                                           IncomingListCache &cache,
                                           const std::vector<string_> &str) {
            auto map = cache.get_map();
            downstream_listed++;
            if (downstream_listed == 1) {
              EXPECT_TRUE(map.find("Test1") != map.end());
              EXPECT_TRUE(map.find("Test2") != map.end());

              link_req->list(
                  "Sys/Clients",
                  [&, link_req](IncomingListCache &cache,
                                const std::vector<string_> &str) {
                    auto map = cache.get_map();
                    bool test1_client = false;
                    string_ test2_id;
                    for (auto &items : map) {
                      if (items.first.substr(0, 5) == "Test1")
                        test1_client = true;
                      else if (items.first.substr(0, 5) == "Test2") {
                        test2_id = items.first;
                      }
                    }
                    clients_listed++;
                    if (clients_listed == 1) {
                      EXPECT_TRUE(test1_client && !test2_id.empty());
                      auto invoke_request = make_ref_<InvokeRequestMessage>();
                      invoke_request->set_target_path("Sys/Clients/" +
                                                      test2_id + "/Remove");

                      link_req->invoke(
                          [&](IncomingInvokeStream &stream,
                              ref_<const InvokeResponseMessage> &&msg) {
                            auto response = std::move(msg);
                            EXPECT_TRUE(response != nullptr);
                            stream.close();
                          },
                          copy_ref_(invoke_request));
                    } else {
                      EXPECT_TRUE(test1_client && test2_id.empty());
                      cache.close();
                    }
                  });

            } else {
              EXPECT_TRUE(map.find("Test1") != map.end());
              EXPECT_TRUE(map.find("Test2") == map.end());
              cache.close();
            }
          });

        },
        std::move(set_request));

  });
  WAIT_EXPECT_TRUE(1000, [&]() -> bool {
    return (link1_connected && (downstream_listed >= 2) &&
            (clients_listed >= 2) && allow_all_set);
  });

  link_1->strand->post([link_1]() { link_1->destroy(); });
  link_2->strand->post([link_2]() { link_2->destroy(); });
  broker->strand->post([broker]() { broker->destroy(); });
  app->close();

  WAIT_EXPECT_TRUE(1000, [&]() -> bool { return app->is_stopped(); });

  if (!app->is_stopped()) {
    app->force_stop();
  }
  app->wait();

  Storage::get_config_bucket().remove_all();
}

TEST_F(BrokerDsLinkTest, ClientPathTest) {
  Storage::get_config_bucket().remove_all();

  // First Create Broker
  auto app = make_shared_<App>();
  auto broker = broker_dslink_test::create_broker(app);
  broker->run();
  ASYNC_EXPECT_TRUE(1000, *broker->strand,
                    [&]() { return broker->get_active_server_port() != 0; });
  int32_t port;

  switch (protocol()) {
    case dsa::ProtocolType::PROT_DSS:
      port = broker->get_active_secure_port();
      break;
    default:
      port = broker->get_active_server_port();
  }

  EXPECT_TRUE(port != 0);

  auto link_1 =
      broker_dslink_test::create_dslink(app, port, "Test1", false, protocol());

  int downstream_listed = 0;
  bool link1_connected = false, test_end = false;
  link_1->connect([&](const shared_ptr_<Connection> connection,
                      ref_<DsLinkRequester> link_req) {
    link1_connected = true;

    link_req->list(
        "Downstream", [&, link_req](IncomingListCache &cache,
                                    const std::vector<string_> &str) {
          auto map = cache.get_map();
          downstream_listed++;
          if (downstream_listed == 1) {
            EXPECT_TRUE(map.find("Test1") != map.end());

            link_req->list("Sys/Clients", [&, link_req](
                                              IncomingListCache &cache,
                                              const std::vector<string_> &str) {
              auto map = cache.get_map();
              string_ test1_id;
              for (auto &items : map) {
                if (items.first.substr(0, 5) == "Test1") {
                  test1_id = items.first;
                }
              }
              EXPECT_TRUE(!test1_id.empty());

              // change path
              auto set_request = make_ref_<SetRequestMessage>();
              set_request->set_value(Var("Downstream/Test_Changed"));
              set_request->set_target_path("Sys/Clients/" + test1_id + "/Path");
              link_req->set(
                  [&, link_req](IncomingSetStream &stream,
                                ref_<const SetResponseMessage> &&msg) {
                    EXPECT_EQ(msg->get_status(), Status::DONE);

                  },
                  std::move(set_request));
              cache.close();

            });

          } else {
            EXPECT_TRUE(map.find("Test1") == map.end());
            EXPECT_TRUE(map.find("Test_Changed") != map.end());
            cache.close();
            test_end = true;
          }
        });

  });
  WAIT_EXPECT_TRUE(1000, [&]() -> bool {
    return (link1_connected && (downstream_listed >= 2) && test_end);
  });

  link_1->strand->post([link_1]() { link_1->destroy(); });
  broker->strand->post([broker]() { broker->destroy(); });
  app->close();

  WAIT_EXPECT_TRUE(1000, [&]() -> bool { return app->is_stopped(); });

  if (!app->is_stopped()) {
    app->force_stop();
  }
  app->wait();

  Storage::get_config_bucket().remove_all();
}

bool get_connected(const shared_ptr_<Connection> &connection) {
  if (!connection) {
    return false;
  } else {
    auto session = connection->session();
    if (!session) {
      return false;
    } else {
      return session->is_connected();
    }
  }
}

TEST_F(BrokerDsLinkTest, QuarantineTest) {
  Storage::get_config_bucket().remove_all();

  // First Create Broker
  auto app = make_shared_<App>();
  auto broker = broker_dslink_test::create_broker(app);
  broker->run();
  ASYNC_EXPECT_TRUE(1000, *broker->strand,
                    [&]() { return broker->get_active_server_port() != 0; });
  int32_t port;

  switch (protocol()) {
    case dsa::ProtocolType::PROT_DSS:
      port = broker->get_active_secure_port();
      break;
    default:
      port = broker->get_active_server_port();
  }

  EXPECT_TRUE(port != 0);

  auto link_1 =
      broker_dslink_test::create_dslink(app, port, "Test1", false, protocol());
  auto link_2 =
      broker_dslink_test::create_dslink(app, port, "Test2", false, protocol());

  int downstream_listed = 0, quarantine_listed = 0;
  bool link1_connected = false, link2_connected = false;
  link_1->connect([&](const shared_ptr_<Connection> connection,
                      ref_<DsLinkRequester> link_req) {
    link1_connected = get_connected(connection);
    EXPECT_TRUE(link1_connected);

    // set request to change value
    auto set_request = make_ref_<SetRequestMessage>();
    set_request->set_value(Var(false));
    set_request->set_target_path("Sys/Clients/Allow_All");

    link_req->set(
        [&, link_req](IncomingSetStream &stream,
                      ref_<const SetResponseMessage> &&msg) {
          EXPECT_EQ(msg->get_status(), Status::DONE);

          // set request to change value
          auto set_request = make_ref_<SetRequestMessage>();
          set_request->set_value(Var(true));
          set_request->set_target_path("Sys/Quarantine/Enabled");

          // send set request
          link_req->set(
              [&, link_req](IncomingSetStream &stream,
                            ref_<const SetResponseMessage> &&msg) {
                EXPECT_EQ(msg->get_status(), Status::DONE);

                link_2->connect([&, link1_req = link_req ](
                    const shared_ptr_<Connection> connection2,
                    ref_<DsLinkRequester> link2_req) {
                  link2_connected = get_connected(connection2);
                  EXPECT_TRUE(link2_connected);
                  link1_req->list(
                      "Downstream",
                      [&, link1_req](IncomingListCache &cache,
                                     const std::vector<string_> &str) {
                        auto map = cache.get_map();
                        downstream_listed++;
                        if (downstream_listed == 1) {
                          EXPECT_TRUE(map.find("Test2") == map.end());
                        } else {
                          EXPECT_TRUE(map.find("Test2") != map.end());
                        }
                      });
                  link1_req->list(
                      "Sys/Quarantine",
                      [&, link1_req](IncomingListCache &cache,
                                     const std::vector<string_> &str) {
                        auto map = cache.get_map();
                        quarantine_listed++;
                        string_ test2_id;
                        for (auto &items : map) {
                          if (items.first.substr(0, 5) == "Test2") {
                            test2_id = items.first;
                          }
                        }
                        if (quarantine_listed == 1) {
                          EXPECT_TRUE(!test2_id.empty());
                          // invoke authorize
                          auto invoke_request =
                              make_ref_<InvokeRequestMessage>();
                          invoke_request->set_target_path(
                              "Sys/Quarantine/" + test2_id + "/Authorize");
                          invoke_request->set_value(
                              Var({{"Path", Var("Downstream/Test2")}}));

                          link1_req->invoke(
                              [&](IncomingInvokeStream &stream,
                                  ref_<const InvokeResponseMessage> &&msg) {
                                auto response = std::move(msg);
                                EXPECT_EQ(response->get_status(),
                                          Status::DONE);
                                EXPECT_TRUE(response != nullptr);
                                stream.close();
                              },
                              copy_ref_(invoke_request));
                        } else {
                          EXPECT_TRUE(test2_id.empty());
                        }
                      });

                });

              },
              std::move(set_request));
        },
        std::move(set_request));

  });
  WAIT_EXPECT_TRUE(3000, [&]() -> bool {
    return (link1_connected && link2_connected && (downstream_listed >= 2) &&
            (quarantine_listed >= 2));
  });

  link_1->strand->post([link_1]() { link_1->destroy(); });
  link_2->strand->post([link_2]() { link_2->destroy(); });
  broker->strand->post([broker]() { broker->destroy(); });
  app->close();

  WAIT_EXPECT_TRUE(1000, [&]() -> bool { return app->is_stopped(); });

  if (!app->is_stopped()) {
    app->force_stop();
  }
  app->wait();

  Storage::get_config_bucket().remove_all();
}

TEST_F(BrokerDsLinkTest, IdenticalClientTest) {
  Storage::get_config_bucket().remove_all();

  // First Create Broker
  auto app = make_shared_<App>();
  auto broker = broker_dslink_test::create_broker(app);
  broker->run();
  ASYNC_EXPECT_TRUE(1000, *broker->strand,
                    [&]() { return broker->get_active_server_port() != 0; });
  int32_t port;

  switch (protocol()) {
    case dsa::ProtocolType::PROT_DSS:
      port = broker->get_active_secure_port();
      break;
    default:
      port = broker->get_active_server_port();
  }

  EXPECT_TRUE(port != 0);

  auto link_1 =
      broker_dslink_test::create_dslink(app, port, "Test1", false, protocol());
  auto link_2 =
      broker_dslink_test::create_dslink(app, port, "Test1", false, protocol());

  bool link1_connected = false;
  bool link2_connected = false;
  link_1->connect([&](const shared_ptr_<Connection> connection,
                      ref_<DsLinkRequester> link_req) {
    link1_connected |= get_connected(connection);

    if (link1_connected) {
      link_2->connect([&](const shared_ptr_<Connection> connection,
                          ref_<DsLinkRequester> link_req) {
        link2_connected |= get_connected(connection);
      });
    }

  });
  WAIT_EXPECT_TRUE(
      1000, [&]() -> bool { return link1_connected && link2_connected; });

  link_1->strand->post([link_1]() { link_1->destroy(); });
  link_2->strand->post([link_2]() { link_2->destroy(); });
  broker->strand->post([broker]() { broker->destroy(); });
  app->close();

  WAIT_EXPECT_TRUE(1000, [&]() -> bool { return app->is_stopped(); });

  if (!app->is_stopped()) {
    app->force_stop();
  }
  app->wait();

  Storage::get_config_bucket().remove_all();
}<commit_msg>keep broker.json and pem files for secure connection unittests<commit_after>#include "broker_dslink_util.h"

using BrokerDsLinkTest = SetUpBase;

void clean_config_files(dsa::ProtocolType protocol) {
  switch (protocol) {
  case ProtocolType::PROT_DSS:
  case ProtocolType::PROT_WSS:
    Storage::get_config_bucket().remove("client-manager.json");
    break;
  default:
    Storage::get_config_bucket().remove_all();
  }
}

TEST_F(BrokerDsLinkTest, ClientRemoveTest) {
  clean_config_files(protocol());

  // First Create Broker
  auto app = make_shared_<App>();
  auto broker = broker_dslink_test::create_broker(app);
  broker->run();
  ASYNC_EXPECT_TRUE(1000, *broker->strand,
                    [&]() { return broker->get_active_server_port() != 0; });
  int32_t port;

  switch (protocol()) {
    case dsa::ProtocolType::PROT_DSS:
      port = broker->get_active_secure_port();
      break;
    default:
      port = broker->get_active_server_port();
  }

  EXPECT_TRUE(port != 0);

  auto link_1 =
      broker_dslink_test::create_dslink(app, port, "Test1", false, protocol());
  auto link_2 =
      broker_dslink_test::create_dslink(app, port, "Test2", true, protocol());

  int downstream_listed = 0, clients_listed = 0;
  bool link1_connected = false, allow_all_set = false;
  link_1->connect([&](const shared_ptr_<Connection> connection,
                      ref_<DsLinkRequester> link_req) {
    link1_connected = true;

    // set request to change value
    auto set_request = make_ref_<SetRequestMessage>();
    set_request->set_value(Var(false));
    set_request->set_target_path("Sys/Clients/Allow_All");

    // send set request
    link_req->set(
        [&, link_req](IncomingSetStream &stream,
                      ref_<const SetResponseMessage> &&msg) {
          EXPECT_TRUE(msg->get_status() == Status::OK ||
                      msg->get_status() == Status::DONE);
          allow_all_set = true;

          link_req->list("Downstream", [&, link_req](
                                           IncomingListCache &cache,
                                           const std::vector<string_> &str) {
            auto map = cache.get_map();
            downstream_listed++;
            if (downstream_listed == 1) {
              EXPECT_TRUE(map.find("Test1") != map.end());
              EXPECT_TRUE(map.find("Test2") != map.end());

              link_req->list(
                  "Sys/Clients",
                  [&, link_req](IncomingListCache &cache,
                                const std::vector<string_> &str) {
                    auto map = cache.get_map();
                    bool test1_client = false;
                    string_ test2_id;
                    for (auto &items : map) {
                      if (items.first.substr(0, 5) == "Test1")
                        test1_client = true;
                      else if (items.first.substr(0, 5) == "Test2") {
                        test2_id = items.first;
                      }
                    }
                    clients_listed++;
                    if (clients_listed == 1) {
                      EXPECT_TRUE(test1_client && !test2_id.empty());
                      auto invoke_request = make_ref_<InvokeRequestMessage>();
                      invoke_request->set_target_path("Sys/Clients/" +
                                                      test2_id + "/Remove");

                      link_req->invoke(
                          [&](IncomingInvokeStream &stream,
                              ref_<const InvokeResponseMessage> &&msg) {
                            auto response = std::move(msg);
                            EXPECT_TRUE(response != nullptr);
                            stream.close();
                          },
                          copy_ref_(invoke_request));
                    } else {
                      EXPECT_TRUE(test1_client && test2_id.empty());
                      cache.close();
                    }
                  });

            } else {
              EXPECT_TRUE(map.find("Test1") != map.end());
              EXPECT_TRUE(map.find("Test2") == map.end());
              cache.close();
            }
          });

        },
        std::move(set_request));

  });
  WAIT_EXPECT_TRUE(1000, [&]() -> bool {
    return (link1_connected && (downstream_listed >= 2) &&
            (clients_listed >= 2) && allow_all_set);
  });

  link_1->strand->post([link_1]() { link_1->destroy(); });
  link_2->strand->post([link_2]() { link_2->destroy(); });
  broker->strand->post([broker]() { broker->destroy(); });
  app->close();

  WAIT_EXPECT_TRUE(1000, [&]() -> bool { return app->is_stopped(); });

  if (!app->is_stopped()) {
    app->force_stop();
  }
  app->wait();

  clean_config_files(protocol());
}

TEST_F(BrokerDsLinkTest, ClientPathTest) {
  clean_config_files(protocol());

  // First Create Broker
  auto app = make_shared_<App>();
  auto broker = broker_dslink_test::create_broker(app);
  broker->run();
  ASYNC_EXPECT_TRUE(1000, *broker->strand,
                    [&]() { return broker->get_active_server_port() != 0; });
  int32_t port;

  switch (protocol()) {
    case dsa::ProtocolType::PROT_DSS:
      port = broker->get_active_secure_port();
      break;
    default:
      port = broker->get_active_server_port();
  }

  EXPECT_TRUE(port != 0);

  auto link_1 =
      broker_dslink_test::create_dslink(app, port, "Test1", false, protocol());

  int downstream_listed = 0;
  bool link1_connected = false, test_end = false;
  link_1->connect([&](const shared_ptr_<Connection> connection,
                      ref_<DsLinkRequester> link_req) {
    link1_connected = true;

    link_req->list(
        "Downstream", [&, link_req](IncomingListCache &cache,
                                    const std::vector<string_> &str) {
          auto map = cache.get_map();
          downstream_listed++;
          if (downstream_listed == 1) {
            EXPECT_TRUE(map.find("Test1") != map.end());

            link_req->list("Sys/Clients", [&, link_req](
                                              IncomingListCache &cache,
                                              const std::vector<string_> &str) {
              auto map = cache.get_map();
              string_ test1_id;
              for (auto &items : map) {
                if (items.first.substr(0, 5) == "Test1") {
                  test1_id = items.first;
                }
              }
              EXPECT_TRUE(!test1_id.empty());

              // change path
              auto set_request = make_ref_<SetRequestMessage>();
              set_request->set_value(Var("Downstream/Test_Changed"));
              set_request->set_target_path("Sys/Clients/" + test1_id + "/Path");
              link_req->set(
                  [&, link_req](IncomingSetStream &stream,
                                ref_<const SetResponseMessage> &&msg) {
                    EXPECT_EQ(msg->get_status(), Status::DONE);

                  },
                  std::move(set_request));
              cache.close();

            });

          } else {
            EXPECT_TRUE(map.find("Test1") == map.end());
            EXPECT_TRUE(map.find("Test_Changed") != map.end());
            cache.close();
            test_end = true;
          }
        });

  });
  WAIT_EXPECT_TRUE(1000, [&]() -> bool {
    return (link1_connected && (downstream_listed >= 2) && test_end);
  });

  link_1->strand->post([link_1]() { link_1->destroy(); });
  broker->strand->post([broker]() { broker->destroy(); });
  app->close();

  WAIT_EXPECT_TRUE(1000, [&]() -> bool { return app->is_stopped(); });

  if (!app->is_stopped()) {
    app->force_stop();
  }
  app->wait();

  clean_config_files(protocol());
}

bool get_connected(const shared_ptr_<Connection> &connection) {
  if (!connection) {
    return false;
  } else {
    auto session = connection->session();
    if (!session) {
      return false;
    } else {
      return session->is_connected();
    }
  }
}

TEST_F(BrokerDsLinkTest, QuarantineTest) {
  clean_config_files(protocol());

  // First Create Broker
  auto app = make_shared_<App>();
  auto broker = broker_dslink_test::create_broker(app);
  broker->run();
  ASYNC_EXPECT_TRUE(1000, *broker->strand,
                    [&]() { return broker->get_active_server_port() != 0; });
  int32_t port;

  switch (protocol()) {
    case dsa::ProtocolType::PROT_DSS:
      port = broker->get_active_secure_port();
      break;
    default:
      port = broker->get_active_server_port();
  }

  EXPECT_TRUE(port != 0);

  auto link_1 =
      broker_dslink_test::create_dslink(app, port, "Test1", false, protocol());
  auto link_2 =
      broker_dslink_test::create_dslink(app, port, "Test2", false, protocol());

  int downstream_listed = 0, quarantine_listed = 0;
  bool link1_connected = false, link2_connected = false;
  link_1->connect([&](const shared_ptr_<Connection> connection,
                      ref_<DsLinkRequester> link_req) {
    link1_connected = get_connected(connection);
    EXPECT_TRUE(link1_connected);

    // set request to change value
    auto set_request = make_ref_<SetRequestMessage>();
    set_request->set_value(Var(false));
    set_request->set_target_path("Sys/Clients/Allow_All");

    link_req->set(
        [&, link_req](IncomingSetStream &stream,
                      ref_<const SetResponseMessage> &&msg) {
          EXPECT_EQ(msg->get_status(), Status::DONE);

          // set request to change value
          auto set_request = make_ref_<SetRequestMessage>();
          set_request->set_value(Var(true));
          set_request->set_target_path("Sys/Quarantine/Enabled");

          // send set request
          link_req->set(
              [&, link_req](IncomingSetStream &stream,
                            ref_<const SetResponseMessage> &&msg) {
                EXPECT_EQ(msg->get_status(), Status::DONE);

                link_2->connect([&, link1_req = link_req ](
                    const shared_ptr_<Connection> connection2,
                    ref_<DsLinkRequester> link2_req) {
                  link2_connected = get_connected(connection2);
                  EXPECT_TRUE(link2_connected);
                  link1_req->list(
                      "Downstream",
                      [&, link1_req](IncomingListCache &cache,
                                     const std::vector<string_> &str) {
                        auto map = cache.get_map();
                        downstream_listed++;
                        if (downstream_listed == 1) {
                          EXPECT_TRUE(map.find("Test2") == map.end());
                        } else {
                          EXPECT_TRUE(map.find("Test2") != map.end());
                        }
                      });
                  link1_req->list(
                      "Sys/Quarantine",
                      [&, link1_req](IncomingListCache &cache,
                                     const std::vector<string_> &str) {
                        auto map = cache.get_map();
                        quarantine_listed++;
                        string_ test2_id;
                        for (auto &items : map) {
                          if (items.first.substr(0, 5) == "Test2") {
                            test2_id = items.first;
                          }
                        }
                        if (quarantine_listed == 1) {
                          EXPECT_TRUE(!test2_id.empty());
                          // invoke authorize
                          auto invoke_request =
                              make_ref_<InvokeRequestMessage>();
                          invoke_request->set_target_path(
                              "Sys/Quarantine/" + test2_id + "/Authorize");
                          invoke_request->set_value(
                              Var({{"Path", Var("Downstream/Test2")}}));

                          link1_req->invoke(
                              [&](IncomingInvokeStream &stream,
                                  ref_<const InvokeResponseMessage> &&msg) {
                                auto response = std::move(msg);
                                EXPECT_EQ(response->get_status(),
                                          Status::DONE);
                                EXPECT_TRUE(response != nullptr);
                                stream.close();
                              },
                              copy_ref_(invoke_request));
                        } else {
                          EXPECT_TRUE(test2_id.empty());
                        }
                      });

                });

              },
              std::move(set_request));
        },
        std::move(set_request));

  });
  WAIT_EXPECT_TRUE(3000, [&]() -> bool {
    return (link1_connected && link2_connected && (downstream_listed >= 2) &&
            (quarantine_listed >= 2));
  });

  link_1->strand->post([link_1]() { link_1->destroy(); });
  link_2->strand->post([link_2]() { link_2->destroy(); });
  broker->strand->post([broker]() { broker->destroy(); });
  app->close();

  WAIT_EXPECT_TRUE(1000, [&]() -> bool { return app->is_stopped(); });

  if (!app->is_stopped()) {
    app->force_stop();
  }
  app->wait();

  clean_config_files(protocol());
}

TEST_F(BrokerDsLinkTest, IdenticalClientTest) {
  clean_config_files(protocol());

  // First Create Broker
  auto app = make_shared_<App>();
  auto broker = broker_dslink_test::create_broker(app);
  broker->run();
  ASYNC_EXPECT_TRUE(1000, *broker->strand,
                    [&]() { return broker->get_active_server_port() != 0; });
  int32_t port;

  switch (protocol()) {
    case dsa::ProtocolType::PROT_DSS:
      port = broker->get_active_secure_port();
      break;
    default:
      port = broker->get_active_server_port();
  }

  EXPECT_TRUE(port != 0);

  auto link_1 =
      broker_dslink_test::create_dslink(app, port, "Test1", false, protocol());
  auto link_2 =
      broker_dslink_test::create_dslink(app, port, "Test1", false, protocol());

  bool link1_connected = false;
  bool link2_connected = false;
  link_1->connect([&](const shared_ptr_<Connection> connection,
                      ref_<DsLinkRequester> link_req) {
    link1_connected |= get_connected(connection);

    if (link1_connected) {
      link_2->connect([&](const shared_ptr_<Connection> connection,
                          ref_<DsLinkRequester> link_req) {
        link2_connected |= get_connected(connection);
      });
    }

  });
  WAIT_EXPECT_TRUE(
      1000, [&]() -> bool { return link1_connected && link2_connected; });

  link_1->strand->post([link_1]() { link_1->destroy(); });
  link_2->strand->post([link_2]() { link_2->destroy(); });
  broker->strand->post([broker]() { broker->destroy(); });
  app->close();

  WAIT_EXPECT_TRUE(1000, [&]() -> bool { return app->is_stopped(); });

  if (!app->is_stopped()) {
    app->force_stop();
  }
  app->wait();

  clean_config_files(protocol());
}
<|endoftext|>


<commit_before>#include	<cstdlib>
#include	<cmath>
#include	<fstream>
#include	<sstream>
#include	<iostream>
#include	<iomanip>
#include	<string>
#include	<vector>
#include	<algorithm>
#include	<exception>
#include	<sys/time.h>
#include	"modules/htmTree.h"
#include	"modules/kdTree.h"
#include        "misc.h"
#include        "feat.h"
#include        "structs.h"
#include        "collision.h"
#include        "global.h"
//reduce redistributes, updates  07/02/15 rnc
int main(int argc, char **argv) {
	//// Initializations ---------------------------------------------
	srand48(1234); // Make sure we have reproducability
	check_args(argc);
	Time t, time; // t for global, time for local
	init_time(t);
	Feat F;
    MTL M;

	// Read parameters file //
	F.readInputFile(argv[1]);
	printFile(argv[1]);
	// Read galaxies
	Gals G;
    if(F.Ascii){
        G=read_galaxies_ascii(F);}
    else{
        G = read_galaxies(F);
    }
	F.Ngal = G.size();
	printf("# Read %s galaxies from %s \n",f(F.Ngal).c_str(),F.galFile.c_str());
    std::vector<int> count;
    count=count_galaxies(G);
    printf(" Number of galaxies by type, QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF\n");
    for(int i=0;i<8;i++){printf (" type %d number  %d  \n",i, count[i]);}
    //read the three input files
    MTL Targ=read_MTLfile(F.Targfile,F);
    MTL SStars=read_MTLfile(F.SStarsfile,F);
    MTL SkyF=read_MTLfile(F.SkyFfile,F);
    //combine the three input files

    M=Targ;
    M.reserve(Targ.size()+SStars.size()+SkyF.size());
    printf(" M size %d \n",M.size());
    M.insert(M.end(),SStars.begin(),SStars.end());
    printf(" M size %d \n",M.size());
    M.insert(M.end(),SkyF.begin(),SkyF.end());
    printf(" M size %d \n",M.size());
    //need to fix priority list, combining those from targets, standard stars, skyfibers
    std::vector<int> p_list=Targ.priority_list;
    p_list.insert(p_list.end(),SStars.priority_list.begin(),SStars.priority_list.end());
    p_list.insert(p_list.end(),SkyF.priority_list.begin(),SkyF.priority_list.end());
    std::sort(p_list.begin(),p_list.end());

    M.priority_list.clear();
    M.priority_list.push_back(p_list[0]);
    for(int i=1;i<p_list.size();++i){
        if(p_list[i]!=p_list[i-1]){
            M.priority_list.push_back(p_list[i]);
            }
    }

    assign_priority_class(M);

    //establish priority classes
    std::vector <int> count_class(M.priority_list.size(),0);
    printf("Number in each priority class.  The last two are SF and SS.\n");
    for(int i;i<M.size();++i){
        count_class[M[i].priority_class]+=1;
    }
    for(int i;i<M.priority_list.size();++i){
        printf("  class  %d  number  %d\n",i,count_class[i]);
    }

	PP pp;
	pp.read_fiber_positions(F);
	F.Nfiber = pp.fp.size()/2;
	F.Npetal = max(pp.spectrom)+1;
    F.Nfbp = (int) (F.Nfiber/F.Npetal);// fibers per petal = 500
	pp.get_neighbors(F); pp.compute_fibsofsp(F);
	Plates OP = read_plate_centers(F);
    Plates P;
    F.ONplate=OP.size();
	printf("# Read %s plate centers from %s and %d fibers from %s\n",f(F.ONplate).c_str(),F.tileFile.c_str(),F.Nfiber,F.fibFile.c_str());

	// Computes geometries of cb and fh: pieces of positioner - used to determine possible collisions
	F.cb = create_cb(); // cb=central body
	F.fh = create_fh(); // fh=fiber holder

	//// Collect available galaxies <-> tilefibers --------------------
	// HTM Tree of galaxies
	const double MinTreeSize = 0.01;
	init_time_at(time,"# Start building HTM tree",t);
	htmTree<struct target> T(M,MinTreeSize);
	print_time(time,"# ... took :");//T.stats();

	// For plates/fibers, collect available galaxies; done in parallel
    collect_galaxies_for_all(M,T,OP,pp,F);

	// For each galaxy, computes available tilefibers  G[i].av_tfs = [(j1,k1),(j2,k2),..]
	collect_available_tilefibers(M,OP,F);

	//results_on_inputs("doc/figs/",G,P,F,true);

	//// Assignment |||||||||||||||||||||||||||||||||||||||||||||||||||
    printf(" Nplate %d  Ngal %d   Nfiber %d \n", F.ONplate, F.Ngal, F.Nfiber);
	Assignment A(M,F);
    printf(" Nplate %d  Ngal %d   Nfiber %d \n", F.ONplate, F.Ngal, F.Nfiber);
	print_time(t,"# Start assignment at : ");

	// Make a plan ----------------------------------------------------
    // Plans whole survey without sky fibers, standard stars
    // assumes maximum number of observations needed for QSOs, LRGs

    simple_assign(M,OP,pp,F,A);

    //check to see if there are tiles with no galaxies
    for (int j=0;j<F.Nplate ;++j){
        int newj=0;
        OP[j].is_used=false;
        bool not_done=true;
        for(int k=0;k<F.Nfiber && not_done;++k){
            if(A.TF[j][k]!=-1){
                OP[j].is_used=true;
                P[newj]=OP[j];
                newj++;
                not_done=false;
            }
        }
    }
    F.Nplate=P.size();
    printf(" Plates after screening %d \",F.Nplate);
    if(F.diagnose)diagnostic(M,G,F,A);

    print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false); // Hist of unused fibs

	// Smooth out distribution of free fibers, and increase the number of assignments

	for (int i=0; i<1; i++) redistribute_tf(M,P,pp,F,A);// more iterations will improve performance slightly
	for (int i=0; i<2; i++) {
        improve(M,P,pp,F,A);
		//redistribute_tf(M,P,pp,F,A);
		redistribute_tf(M,P,pp,F,A);
	}

	print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false);
    //try assigning SF and SS before real time assignment
    for (int j=0;j<F.Nplate;++j){
        A.next_plate=j;
        assign_sf_ss(j,M,P,pp,F,A); // Assign SS and SF for each tile
        assign_unused(j,M,P,pp,F,A);
    }

    init_time_at(time,"# Begin real time assignment",t);

	//Execute plan, updating targets at intervals

    for(int i=0;i<F.pass_intervals.size();++i){
        printf(" before pass = %d  at %d  tiles\n",i,F.pass_intervals[i]);
        //display_results("doc/figs/",G,P,pp,F,A,true);
        //execute this phase (i) of survey
        A.next_plate=F.pass_intervals[i];
        for (int jj=F.pass_intervals[i]; jj<F.Nplate&&jj<F.Nplate; jj++) {
            int j = A.next_plate;
            assign_sf_ss(j,M,P,pp,F,A); // Assign SS and SF
            assign_unused(j,M,P,pp,F,A);
            A.next_plate++;
        }
        //update target information for this interval
        A.next_plate=F.pass_intervals[i];
        for (int jj=F.pass_intervals[i]; jj<F.pass_intervals[i+1]&&jj<F.Nplate; jj++) {
            int j = A.next_plate;

            // Update corrects all future occurrences of wrong QSOs etc and tries to observe something else
            if (0<=j-F.Analysis) update_plan_from_one_obs(G,M,P,pp,F,A,F.Nplate-1); else printf("\n");
            A.next_plate++;
        }
        /*
        if(A.next_plate<F.Nplate){
        redistribute_tf(M,P,pp,F,A);
        redistribute_tf(M,P,pp,F,A);
        improve(M,P,pp,F,A);
        redistribute_tf(M,P,pp,F,A);
        }
         */
        if(F.diagnose)diagnostic(M,G,F,A);
    }

	// Results -------------------------------------------------------
    if (F.PrintAscii) for (int j=0; j<F.Nplate; j++){
        write_FAtile_ascii(j,F.outDir,M,P,pp,F,A);
    }

    if (F.PrintFits) for (int j=0; j<F.Nplate; j++){
        fa_write(j,F.outDir,M,P,pp,F,A); // Write output
    }

	display_results("doc/figs/",G,M,P,pp,F,A,true);
	if (F.Verif) A.verif(P,M,pp,F); // Verification that the assignment is sane

	print_time(t,"# Finished !... in");

	return(0);

}
<commit_msg>print F.Nplate<commit_after>#include	<cstdlib>
#include	<cmath>
#include	<fstream>
#include	<sstream>
#include	<iostream>
#include	<iomanip>
#include	<string>
#include	<vector>
#include	<algorithm>
#include	<exception>
#include	<sys/time.h>
#include	"modules/htmTree.h"
#include	"modules/kdTree.h"
#include        "misc.h"
#include        "feat.h"
#include        "structs.h"
#include        "collision.h"
#include        "global.h"
//reduce redistributes, updates  07/02/15 rnc
int main(int argc, char **argv) {
	//// Initializations ---------------------------------------------
	srand48(1234); // Make sure we have reproducability
	check_args(argc);
	Time t, time; // t for global, time for local
	init_time(t);
	Feat F;
    MTL M;

	// Read parameters file //
	F.readInputFile(argv[1]);
	printFile(argv[1]);
	// Read galaxies
	Gals G;
    if(F.Ascii){
        G=read_galaxies_ascii(F);}
    else{
        G = read_galaxies(F);
    }
	F.Ngal = G.size();
	printf("# Read %s galaxies from %s \n",f(F.Ngal).c_str(),F.galFile.c_str());
    std::vector<int> count;
    count=count_galaxies(G);
    printf(" Number of galaxies by type, QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF\n");
    for(int i=0;i<8;i++){printf (" type %d number  %d  \n",i, count[i]);}
    //read the three input files
    MTL Targ=read_MTLfile(F.Targfile,F);
    MTL SStars=read_MTLfile(F.SStarsfile,F);
    MTL SkyF=read_MTLfile(F.SkyFfile,F);
    //combine the three input files

    M=Targ;
    M.reserve(Targ.size()+SStars.size()+SkyF.size());
    printf(" M size %d \n",M.size());
    M.insert(M.end(),SStars.begin(),SStars.end());
    printf(" M size %d \n",M.size());
    M.insert(M.end(),SkyF.begin(),SkyF.end());
    printf(" M size %d \n",M.size());
    //need to fix priority list, combining those from targets, standard stars, skyfibers
    std::vector<int> p_list=Targ.priority_list;
    p_list.insert(p_list.end(),SStars.priority_list.begin(),SStars.priority_list.end());
    p_list.insert(p_list.end(),SkyF.priority_list.begin(),SkyF.priority_list.end());
    std::sort(p_list.begin(),p_list.end());

    M.priority_list.clear();
    M.priority_list.push_back(p_list[0]);
    for(int i=1;i<p_list.size();++i){
        if(p_list[i]!=p_list[i-1]){
            M.priority_list.push_back(p_list[i]);
            }
    }

    assign_priority_class(M);

    //establish priority classes
    std::vector <int> count_class(M.priority_list.size(),0);
    printf("Number in each priority class.  The last two are SF and SS.\n");
    for(int i;i<M.size();++i){
        count_class[M[i].priority_class]+=1;
    }
    for(int i;i<M.priority_list.size();++i){
        printf("  class  %d  number  %d\n",i,count_class[i]);
    }

	PP pp;
	pp.read_fiber_positions(F);
	F.Nfiber = pp.fp.size()/2;
	F.Npetal = max(pp.spectrom)+1;
    F.Nfbp = (int) (F.Nfiber/F.Npetal);// fibers per petal = 500
	pp.get_neighbors(F); pp.compute_fibsofsp(F);
	Plates OP = read_plate_centers(F);
    Plates P;
    F.ONplate=OP.size();
	printf("# Read %s plate centers from %s and %d fibers from %s\n",f(F.ONplate).c_str(),F.tileFile.c_str(),F.Nfiber,F.fibFile.c_str());

	// Computes geometries of cb and fh: pieces of positioner - used to determine possible collisions
	F.cb = create_cb(); // cb=central body
	F.fh = create_fh(); // fh=fiber holder

	//// Collect available galaxies <-> tilefibers --------------------
	// HTM Tree of galaxies
	const double MinTreeSize = 0.01;
	init_time_at(time,"# Start building HTM tree",t);
	htmTree<struct target> T(M,MinTreeSize);
	print_time(time,"# ... took :");//T.stats();

	// For plates/fibers, collect available galaxies; done in parallel
    collect_galaxies_for_all(M,T,OP,pp,F);

	// For each galaxy, computes available tilefibers  G[i].av_tfs = [(j1,k1),(j2,k2),..]
	collect_available_tilefibers(M,OP,F);

	//results_on_inputs("doc/figs/",G,P,F,true);

	//// Assignment |||||||||||||||||||||||||||||||||||||||||||||||||||
    printf(" Nplate %d  Ngal %d   Nfiber %d \n", F.ONplate, F.Ngal, F.Nfiber);
	Assignment A(M,F);
    printf(" Nplate %d  Ngal %d   Nfiber %d \n", F.ONplate, F.Ngal, F.Nfiber);
	print_time(t,"# Start assignment at : ");

	// Make a plan ----------------------------------------------------
    // Plans whole survey without sky fibers, standard stars
    // assumes maximum number of observations needed for QSOs, LRGs

    simple_assign(M,OP,pp,F,A);

    //check to see if there are tiles with no galaxies
    for (int j=0;j<F.Nplate ;++j){
        int newj=0;
        OP[j].is_used=false;
        bool not_done=true;
        for(int k=0;k<F.Nfiber && not_done;++k){
            if(A.TF[j][k]!=-1){
                OP[j].is_used=true;
                P[newj]=OP[j];
                newj++;
                not_done=false;
            }
        }
    }
    F.Nplate=P.size();
    printf(" Plates after screening %d \n",F.Nplate);
    if(F.diagnose)diagnostic(M,G,F,A);

    print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false); // Hist of unused fibs

	// Smooth out distribution of free fibers, and increase the number of assignments

	for (int i=0; i<1; i++) redistribute_tf(M,P,pp,F,A);// more iterations will improve performance slightly
	for (int i=0; i<2; i++) {
        improve(M,P,pp,F,A);
		//redistribute_tf(M,P,pp,F,A);
		redistribute_tf(M,P,pp,F,A);
	}

	print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false);
    //try assigning SF and SS before real time assignment
    for (int j=0;j<F.Nplate;++j){
        A.next_plate=j;
        assign_sf_ss(j,M,P,pp,F,A); // Assign SS and SF for each tile
        assign_unused(j,M,P,pp,F,A);
    }

    init_time_at(time,"# Begin real time assignment",t);

	//Execute plan, updating targets at intervals

    for(int i=0;i<F.pass_intervals.size();++i){
        printf(" before pass = %d  at %d  tiles\n",i,F.pass_intervals[i]);
        //display_results("doc/figs/",G,P,pp,F,A,true);
        //execute this phase (i) of survey
        A.next_plate=F.pass_intervals[i];
        for (int jj=F.pass_intervals[i]; jj<F.Nplate&&jj<F.Nplate; jj++) {
            int j = A.next_plate;
            assign_sf_ss(j,M,P,pp,F,A); // Assign SS and SF
            assign_unused(j,M,P,pp,F,A);
            A.next_plate++;
        }
        //update target information for this interval
        A.next_plate=F.pass_intervals[i];
        for (int jj=F.pass_intervals[i]; jj<F.pass_intervals[i+1]&&jj<F.Nplate; jj++) {
            int j = A.next_plate;

            // Update corrects all future occurrences of wrong QSOs etc and tries to observe something else
            if (0<=j-F.Analysis) update_plan_from_one_obs(G,M,P,pp,F,A,F.Nplate-1); else printf("\n");
            A.next_plate++;
        }
        /*
        if(A.next_plate<F.Nplate){
        redistribute_tf(M,P,pp,F,A);
        redistribute_tf(M,P,pp,F,A);
        improve(M,P,pp,F,A);
        redistribute_tf(M,P,pp,F,A);
        }
         */
        if(F.diagnose)diagnostic(M,G,F,A);
    }

	// Results -------------------------------------------------------
    if (F.PrintAscii) for (int j=0; j<F.Nplate; j++){
        write_FAtile_ascii(j,F.outDir,M,P,pp,F,A);
    }

    if (F.PrintFits) for (int j=0; j<F.Nplate; j++){
        fa_write(j,F.outDir,M,P,pp,F,A); // Write output
    }

	display_results("doc/figs/",G,M,P,pp,F,A,true);
	if (F.Verif) A.verif(P,M,pp,F); // Verification that the assignment is sane

	print_time(t,"# Finished !... in");

	return(0);

}
<|endoftext|>


<commit_before>
#pragma once

#include <experimental/optional>
#include <string>

#include "astronomy/frames.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "physics/ephemeris.hpp"
#include "physics/kepler_orbit.hpp"
#include "physics/rigid_motion.hpp"
#include "physics/solar_system.hpp"
#include "testing_utilities/numerics.hpp"
#include "testing_utilities/solar_system_factory.hpp"

namespace principia {

using geometry::AngleBetween;
using geometry::BarycentreCalculator;
using geometry::Bivector;
using geometry::Commutator;
using geometry::Rotation;
using geometry::Velocity;
using geometry::Wedge;
using physics::DegreesOfFreedom;
using physics::Ephemeris;
using physics::KeplerianElements;
using physics::KeplerOrbit;
using physics::RelativeDegreesOfFreedom;
using physics::RigidMotion;
using physics::RotatingBody;
using physics::SolarSystem;
using quantities::AngularMomentum;
using quantities::GravitationalParameter;
using quantities::si::Metre;
using quantities::si::Milli;
using quantities::si::Minute;
using quantities::si::Radian;
using testing_utilities::SolarSystemFactory;
using testing_utilities::AbsoluteError;
using ::testing::AllOf;
using ::testing::Gt;
using ::testing::Lt;

namespace astronomy {

class SolarSystemDynamicsTest : public testing::Test {
 protected:
  struct OrbitError {
    Angle separation_per_orbit;
    Angle inclination_drift_per_orbit;
    std::experimental::optional<Angle>
        longitude_of_ascending_node_drift_per_orbit;
    std::experimental::optional<Angle>
        argument_of_periapsis_drift_per_orbit;
  };

  SolarSystemDynamicsTest() {
#if 1
    google::LogToStderr();
#endif
    for (int primary = 0; primary <= SolarSystemFactory::LastBody; ++primary) {
      for (int i = 1; i <= SolarSystemFactory::LastBody; ++i) {
        if (SolarSystemFactory::parent(i) == primary) {
          bodies_orbiting_[primary].emplace_back(i);
        }
      }
    }
  }

  OrbitError CompareOrbits(
      int const index,
      Ephemeris<ICRFJ2000Equator> const& ephemeris,
      SolarSystem<ICRFJ2000Equator> const& system,
      SolarSystem<ICRFJ2000Equator> const& expected_system) {
    Instant const& epoch = expected_system.epoch();
    Time const duration = epoch - system.epoch();

    auto const name = SolarSystemFactory::name(index);
    auto const parent_name =
        SolarSystemFactory::name(SolarSystemFactory::parent(index));
    auto const body = system.massive_body(ephemeris, name);
    auto const* const parent =
        dynamic_cast<RotatingBody<ICRFJ2000Equator> const*>(
            &*system.massive_body(ephemeris, parent_name));

    BarycentreCalculator<DegreesOfFreedom<ICRFJ2000Equator>,
                         GravitationalParameter> actual_subsystem_barycentre;
    BarycentreCalculator<DegreesOfFreedom<ICRFJ2000Equator>,
                         GravitationalParameter> expected_subsystem_barycentre;

    actual_subsystem_barycentre.Add(
        ephemeris.trajectory(body)->
            EvaluateDegreesOfFreedom(epoch, /*hint=*/nullptr),
        body->gravitational_parameter());
    expected_subsystem_barycentre.Add(expected_system.initial_state(name),
                                      body->gravitational_parameter());
    for (int const moon_index : bodies_orbiting_[index]) {
      auto const moon_name = SolarSystemFactory::name(moon_index);
      auto const moon = system.massive_body(ephemeris, moon_name);
      actual_subsystem_barycentre.Add(
          ephemeris.trajectory(moon)->
              EvaluateDegreesOfFreedom(epoch, /*hint=*/nullptr),
          moon->gravitational_parameter());
      expected_subsystem_barycentre.Add(
          expected_system.initial_state(moon_name),
          moon->gravitational_parameter());
    }

    auto const actual_dof = actual_subsystem_barycentre.Get();
    auto const expected_dof = expected_subsystem_barycentre.Get();

    auto const actual_parent_dof =
        ephemeris.trajectory(parent)->
            EvaluateDegreesOfFreedom(epoch, /*hint=*/nullptr);
    auto const expected_parent_dof =
        expected_system.initial_state(parent_name);

    // We transform to a frame in which |parent| has the z-axis as its rotation
    // axis by rotating around the normal to Earth's and |parent|'s rotation
    // axes.
    // If |parent| is the Sun, we use the normal to the invariable plane instead
    // of the Sun's axis.
    // TODO(egg): perhaps rotating bodies should export a rotation to their
    // celestial reference frame, we'll use that in the plugin too.
    enum LocalFrameTag { tag };
    using ParentEquator = Frame<LocalFrameTag, tag, /*frame_is_inertial=*/true>;
    auto const z = Bivector<double, ICRFJ2000Equator>({0, 0, 1});
    std::experimental::optional<Rotation<ICRFJ2000Equator, ParentEquator>>
        rotation;

    if (SolarSystemFactory::parent(index) == SolarSystemFactory::Sun) {
      Bivector<AngularMomentum, ICRFJ2000Equator>
          solar_system_angular_momentum;
      for (int i = 1; i <= SolarSystemFactory::LastBody; ++i) {
        auto const body_name = SolarSystemFactory::name(i);
        auto const body = system.massive_body(ephemeris, body_name);
        RelativeDegreesOfFreedom<ICRFJ2000Equator> const
            from_solar_system_barycentre =
                expected_system.initial_state(body_name) -
                DegreesOfFreedom<ICRFJ2000Equator>(ICRFJ2000Equator::origin,
                                                   {});
        solar_system_angular_momentum +=
            Wedge(from_solar_system_barycentre.displacement(),
                  body->mass() * from_solar_system_barycentre.velocity()) *
            Radian;
      }
      auto const normal =
          Commutator(Normalize(solar_system_angular_momentum), z);
      // Check that we computed the invariable plane properly by computing its
      // angle to the Sun's equator.
      // The actual figure is "almost exactly 6 deg", see Bailey, Batygin, and
      // Brown, Solar Obliquity Induced by Planet Nine,
      // https://arxiv.org/pdf/1607.03963.pdf.
      EXPECT_THAT(AngleBetween(solar_system_angular_momentum,
                               parent->angular_velocity()),
                  AllOf(Gt(5.9 * Degree), Lt(6.0 * Degree)));
      auto const declination_of_invariable_plane =
          AngleBetween(solar_system_angular_momentum, z);
      rotation =
          Rotation<ICRFJ2000Equator, ParentEquator>(
              declination_of_invariable_plane,
              normal);
    } else {
      auto const ω = parent->angular_velocity();
      auto const normal = Commutator(Normalize(ω), z);
      auto const parent_axis_declination = AngleBetween(ω, z);
      rotation =
          Rotation<ICRFJ2000Equator, ParentEquator>(parent_axis_declination,
                                                    normal);
    }
    RigidMotion<ICRFJ2000Equator, ParentEquator> const
        to_parent_equator(
            {ICRFJ2000Equator::origin,
             ParentEquator::origin,
             rotation->Forget()},
            /*angular_velocity_of_to_frame=*/{},
            /*velocity_of_to_frame_origin=*/{});

    KeplerOrbit<ParentEquator> actual_osculating_orbit(
        /*primary=*/*parent,
        /*secondary=*/*body,
        /*state_vectors=*/to_parent_equator(actual_dof) -
            to_parent_equator(actual_parent_dof),
        epoch);
    KeplerOrbit<ParentEquator> expected_osculating_orbit(
        /*primary=*/*parent,
        /*secondary=*/*body,
        /*state_vectors=*/to_parent_equator(expected_dof) -
            to_parent_equator(expected_parent_dof),
        epoch);
    KeplerianElements<ParentEquator> const& actual_elements =
        actual_osculating_orbit.elements_at_epoch();
    KeplerianElements<ParentEquator> const& expected_elements =
        expected_osculating_orbit.elements_at_epoch();

    Time const period = 2 * π * Radian / *actual_elements.mean_motion;
    double const orbits = duration / period;

    OrbitError result;
    result.separation_per_orbit =
        AngleBetween(actual_dof.position() - actual_parent_dof.position(),
                     expected_dof.position() - expected_parent_dof.position()) /
        orbits;
    result.inclination_drift_per_orbit =
        AbsoluteError(expected_elements.inclination,
                      actual_elements.inclination) / orbits;
    if (actual_elements.inclination > 0.1 * Degree) {
      result.longitude_of_ascending_node_drift_per_orbit =
          AbsoluteError(expected_elements.longitude_of_ascending_node,
                        actual_elements.longitude_of_ascending_node) / orbits;

      if (actual_elements.eccentricity > 0.1) {
        result.argument_of_periapsis_drift_per_orbit =
            AbsoluteError(expected_elements.argument_of_periapsis,
                          actual_elements.argument_of_periapsis) / orbits;
      }
    }
    return result;
  }

  std::map<int, std::vector<int>> bodies_orbiting_;
};

TEST_F(SolarSystemDynamicsTest, TwentyDaysFromJ2000) {
  SolarSystem<ICRFJ2000Equator> solar_system_at_j2000;
  solar_system_at_j2000.Initialize(
      SOLUTION_DIR / "astronomy" / "gravity_model.proto.txt",
      SOLUTION_DIR / "astronomy" /
          "initial_state_jd_2451545_000000000.proto.txt");

  SolarSystem<ICRFJ2000Equator> twenty_days_later;
  twenty_days_later.Initialize(
      SOLUTION_DIR / "astronomy" / "gravity_model.proto.txt",
      SOLUTION_DIR / "astronomy" /
          "initial_state_jd_2455200_500000000.proto.txt");

  auto const ephemeris =
      solar_system_at_j2000.MakeEphemeris(
          /*fitting_tolerance=*/5 * Milli(Metre),
          Ephemeris<ICRFJ2000Equator>::FixedStepParameters(
              integrators::BlanesMoan2002SRKN14A<Position<ICRFJ2000Equator>>(),
              /*step=*/45 * Minute));
  ephemeris->Prolong(twenty_days_later.epoch());

  for (int const planet_or_minor_planet :
       bodies_orbiting_[SolarSystemFactory::Sun]) {
    LOG(INFO) << "=== " << SolarSystemFactory::name(planet_or_minor_planet);
    auto const error = CompareOrbits(planet_or_minor_planet,
                                     *ephemeris,
                                     solar_system_at_j2000,
                                     twenty_days_later);
    LOG(INFO) << "separation = " << std::fixed
              << error.separation_per_orbit / ArcSecond << u8"″/orbit";
    LOG(INFO) << u8"Δi         = " << std::fixed
              << error.inclination_drift_per_orbit / ArcSecond << u8"″/orbit";
    if (error.longitude_of_ascending_node_drift_per_orbit) {
      LOG(INFO) << u8"ΔΩ         = " << std::fixed
                << *error.longitude_of_ascending_node_drift_per_orbit /
                       ArcSecond
                << u8"″/orbit";
    }
    if (error.argument_of_periapsis_drift_per_orbit) {
      LOG(INFO) << u8"Δω         = " << std::fixed
                << *error.argument_of_periapsis_drift_per_orbit /
                       ArcSecond
                << u8"″/orbit";
    }

    // This is about the order of magnitude we'd expect from GR for either of
    // those bodies; since it's a combination of perihelion precession and
    // change in anomaly, it's hard to get an exact figure for that.
    if (planet_or_minor_planet == SolarSystemFactory::Mercury ||
        planet_or_minor_planet == SolarSystemFactory::Venus) {
      EXPECT_THAT(
          error.separation_per_orbit,
          AllOf(Gt(100 * Milli(ArcSecond)), Lt(200 * Milli(ArcSecond))));
    }
    else {
      EXPECT_THAT(error.separation_per_orbit, Lt(100 * Milli(ArcSecond)));
    }

    if (error.argument_of_periapsis_drift_per_orbit) {
      if (planet_or_minor_planet == SolarSystemFactory::Mercury) {
        // This is what we expect from GR to the last sigfig.
        EXPECT_THAT(
          *error.argument_of_periapsis_drift_per_orbit,
          AllOf(Gt(102 * Milli(ArcSecond)), Lt(104 * Milli(ArcSecond))));
      } else {
        EXPECT_THAT(*error.argument_of_periapsis_drift_per_orbit,
                    Lt(50 * Milli(ArcSecond)));
      }
    }

    EXPECT_THAT(error.inclination_drift_per_orbit, Lt(0.5 * Milli(ArcSecond)));
  }
}

TEST_F(SolarSystemDynamicsTest, Спутник1ToСпутник2) {
}

}  // namespace astronomy
}  // namespace principia
<commit_msg>moons<commit_after>
#pragma once

#include <experimental/optional>
#include <string>

#include "astronomy/frames.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "physics/ephemeris.hpp"
#include "physics/kepler_orbit.hpp"
#include "physics/rigid_motion.hpp"
#include "physics/solar_system.hpp"
#include "testing_utilities/numerics.hpp"
#include "testing_utilities/solar_system_factory.hpp"

namespace principia {

using geometry::AngleBetween;
using geometry::BarycentreCalculator;
using geometry::Bivector;
using geometry::Commutator;
using geometry::Rotation;
using geometry::Velocity;
using geometry::Wedge;
using physics::DegreesOfFreedom;
using physics::Ephemeris;
using physics::KeplerianElements;
using physics::KeplerOrbit;
using physics::RelativeDegreesOfFreedom;
using physics::RigidMotion;
using physics::RotatingBody;
using physics::SolarSystem;
using quantities::AngularMomentum;
using quantities::GravitationalParameter;
using quantities::si::Metre;
using quantities::si::Milli;
using quantities::si::Minute;
using quantities::si::Radian;
using testing_utilities::SolarSystemFactory;
using testing_utilities::AbsoluteError;
using ::testing::AllOf;
using ::testing::Gt;
using ::testing::Lt;

namespace astronomy {

class SolarSystemDynamicsTest : public testing::Test {
 protected:
  struct OrbitError {
    Angle separation_per_orbit;
    Angle inclination_drift_per_orbit;
    std::experimental::optional<Angle>
        longitude_of_ascending_node_drift_per_orbit;
    std::experimental::optional<Angle>
        argument_of_periapsis_drift_per_orbit;
  };

  SolarSystemDynamicsTest() {
#if 1
    google::LogToStderr();
#endif
    for (int primary = 0; primary <= SolarSystemFactory::LastBody; ++primary) {
      for (int i = 1; i <= SolarSystemFactory::LastBody; ++i) {
        if (SolarSystemFactory::parent(i) == primary) {
          bodies_orbiting_[primary].emplace_back(i);
        }
      }
    }
  }

  OrbitError CompareOrbits(
      int const index,
      Ephemeris<ICRFJ2000Equator> const& ephemeris,
      SolarSystem<ICRFJ2000Equator> const& system,
      SolarSystem<ICRFJ2000Equator> const& expected_system) {
    Instant const& epoch = expected_system.epoch();
    Time const duration = epoch - system.epoch();

    auto const name = SolarSystemFactory::name(index);
    auto const parent_name =
        SolarSystemFactory::name(SolarSystemFactory::parent(index));
    auto const body = system.massive_body(ephemeris, name);
    auto const* const parent =
        dynamic_cast<RotatingBody<ICRFJ2000Equator> const*>(
            &*system.massive_body(ephemeris, parent_name));

    BarycentreCalculator<DegreesOfFreedom<ICRFJ2000Equator>,
                         GravitationalParameter> actual_subsystem_barycentre;
    BarycentreCalculator<DegreesOfFreedom<ICRFJ2000Equator>,
                         GravitationalParameter> expected_subsystem_barycentre;

    actual_subsystem_barycentre.Add(
        ephemeris.trajectory(body)->
            EvaluateDegreesOfFreedom(epoch, /*hint=*/nullptr),
        body->gravitational_parameter());
    expected_subsystem_barycentre.Add(expected_system.initial_state(name),
                                      body->gravitational_parameter());
    for (int const moon_index : bodies_orbiting_[index]) {
      auto const moon_name = SolarSystemFactory::name(moon_index);
      auto const moon = system.massive_body(ephemeris, moon_name);
      actual_subsystem_barycentre.Add(
          ephemeris.trajectory(moon)->
              EvaluateDegreesOfFreedom(epoch, /*hint=*/nullptr),
          moon->gravitational_parameter());
      expected_subsystem_barycentre.Add(
          expected_system.initial_state(moon_name),
          moon->gravitational_parameter());
    }

    auto const actual_dof = actual_subsystem_barycentre.Get();
    auto const expected_dof = expected_subsystem_barycentre.Get();

    auto const actual_parent_dof =
        ephemeris.trajectory(parent)->
            EvaluateDegreesOfFreedom(epoch, /*hint=*/nullptr);
    auto const expected_parent_dof =
        expected_system.initial_state(parent_name);

    // We transform to a frame in which |parent| has the z-axis as its rotation
    // axis by rotating around the normal to Earth's and |parent|'s rotation
    // axes.
    // If |parent| is the Sun, we use the normal to the invariable plane instead
    // of the Sun's axis.
    // TODO(egg): perhaps rotating bodies should export a rotation to their
    // celestial reference frame, we'll use that in the plugin too.
    enum LocalFrameTag { tag };
    using ParentEquator = Frame<LocalFrameTag, tag, /*frame_is_inertial=*/true>;
    auto const z = Bivector<double, ICRFJ2000Equator>({0, 0, 1});
    std::experimental::optional<Rotation<ICRFJ2000Equator, ParentEquator>>
        rotation;

    if (SolarSystemFactory::parent(index) == SolarSystemFactory::Sun) {
      Bivector<AngularMomentum, ICRFJ2000Equator>
          solar_system_angular_momentum;
      for (int i = 1; i <= SolarSystemFactory::LastBody; ++i) {
        auto const body_name = SolarSystemFactory::name(i);
        auto const body = system.massive_body(ephemeris, body_name);
        RelativeDegreesOfFreedom<ICRFJ2000Equator> const
            from_solar_system_barycentre =
                expected_system.initial_state(body_name) -
                DegreesOfFreedom<ICRFJ2000Equator>(ICRFJ2000Equator::origin,
                                                   {});
        solar_system_angular_momentum +=
            Wedge(from_solar_system_barycentre.displacement(),
                  body->mass() * from_solar_system_barycentre.velocity()) *
            Radian;
      }
      auto const normal =
          Commutator(Normalize(solar_system_angular_momentum), z);
      // Check that we computed the invariable plane properly by computing its
      // angle to the Sun's equator.
      // The actual figure is "almost exactly 6 deg", see Bailey, Batygin, and
      // Brown, Solar Obliquity Induced by Planet Nine,
      // https://arxiv.org/pdf/1607.03963.pdf.
      EXPECT_THAT(AngleBetween(solar_system_angular_momentum,
                               parent->angular_velocity()),
                  AllOf(Gt(5.9 * Degree), Lt(6.0 * Degree)));
      auto const declination_of_invariable_plane =
          AngleBetween(solar_system_angular_momentum, z);
      rotation =
          Rotation<ICRFJ2000Equator, ParentEquator>(
              declination_of_invariable_plane,
              normal);
    } else {
      auto const ω = parent->angular_velocity();
      auto const normal = Commutator(Normalize(ω), z);
      auto const parent_axis_declination = AngleBetween(ω, z);
      rotation =
          Rotation<ICRFJ2000Equator, ParentEquator>(parent_axis_declination,
                                                    normal);
    }
    RigidMotion<ICRFJ2000Equator, ParentEquator> const
        to_parent_equator(
            {ICRFJ2000Equator::origin,
             ParentEquator::origin,
             rotation->Forget()},
            /*angular_velocity_of_to_frame=*/{},
            /*velocity_of_to_frame_origin=*/{});

    KeplerOrbit<ParentEquator> actual_osculating_orbit(
        /*primary=*/*parent,
        /*secondary=*/*body,
        /*state_vectors=*/to_parent_equator(actual_dof) -
            to_parent_equator(actual_parent_dof),
        epoch);
    KeplerOrbit<ParentEquator> expected_osculating_orbit(
        /*primary=*/*parent,
        /*secondary=*/*body,
        /*state_vectors=*/to_parent_equator(expected_dof) -
            to_parent_equator(expected_parent_dof),
        epoch);
    KeplerianElements<ParentEquator> const& actual_elements =
        actual_osculating_orbit.elements_at_epoch();
    KeplerianElements<ParentEquator> const& expected_elements =
        expected_osculating_orbit.elements_at_epoch();

    Time const period = 2 * π * Radian / *actual_elements.mean_motion;
    double const orbits = duration / period;

    OrbitError result;
    result.separation_per_orbit =
        AngleBetween(actual_dof.position() - actual_parent_dof.position(),
                     expected_dof.position() - expected_parent_dof.position()) /
        orbits;
    result.inclination_drift_per_orbit =
        AbsoluteError(expected_elements.inclination,
                      actual_elements.inclination) / orbits;
    if (actual_elements.inclination > 0.1 * Degree) {
      result.longitude_of_ascending_node_drift_per_orbit =
          AbsoluteError(expected_elements.longitude_of_ascending_node,
                        actual_elements.longitude_of_ascending_node) / orbits;

      if (actual_elements.eccentricity > 0.1) {
        result.argument_of_periapsis_drift_per_orbit =
            AbsoluteError(expected_elements.argument_of_periapsis,
                          actual_elements.argument_of_periapsis) / orbits;
      }
    }
    return result;
  }

  std::map<int, std::vector<int>> bodies_orbiting_;
};

TEST_F(SolarSystemDynamicsTest, TwentyDaysFromJ2000) {
  SolarSystem<ICRFJ2000Equator> solar_system_at_j2000;
  solar_system_at_j2000.Initialize(
      SOLUTION_DIR / "astronomy" / "gravity_model.proto.txt",
      SOLUTION_DIR / "astronomy" /
          "initial_state_jd_2451545_000000000.proto.txt");

  SolarSystem<ICRFJ2000Equator> twenty_days_later;
  twenty_days_later.Initialize(
      SOLUTION_DIR / "astronomy" / "gravity_model.proto.txt",
      SOLUTION_DIR / "astronomy" /
          "initial_state_jd_2455200_500000000.proto.txt");

  auto const ephemeris =
      solar_system_at_j2000.MakeEphemeris(
          /*fitting_tolerance=*/5 * Milli(Metre),
          Ephemeris<ICRFJ2000Equator>::FixedStepParameters(
              integrators::BlanesMoan2002SRKN14A<Position<ICRFJ2000Equator>>(),
              /*step=*/45 * Minute));
  ephemeris->Prolong(twenty_days_later.epoch());

  for (int const planet_or_minor_planet :
       bodies_orbiting_[SolarSystemFactory::Sun]) {
    LOG(INFO) << "=== " << SolarSystemFactory::name(planet_or_minor_planet);
    auto const error = CompareOrbits(planet_or_minor_planet,
                                     *ephemeris,
                                     solar_system_at_j2000,
                                     twenty_days_later);
    LOG(INFO) << "separation = " << std::fixed
              << error.separation_per_orbit / ArcSecond << u8"″/orbit";
    LOG(INFO) << u8"Δi         = " << std::fixed
              << error.inclination_drift_per_orbit / ArcSecond << u8"″/orbit";
    if (error.longitude_of_ascending_node_drift_per_orbit) {
      LOG(INFO) << u8"ΔΩ         = " << std::fixed
                << *error.longitude_of_ascending_node_drift_per_orbit /
                       ArcSecond
                << u8"″/orbit";
    }
    if (error.argument_of_periapsis_drift_per_orbit) {
      LOG(INFO) << u8"Δω         = " << std::fixed
                << *error.argument_of_periapsis_drift_per_orbit /
                       ArcSecond
                << u8"″/orbit";
    }

    // This is about the order of magnitude we'd expect from GR for either of
    // those bodies; since it's a combination of perihelion precession and
    // change in anomaly, it's hard to get an exact figure for that.
    if (planet_or_minor_planet == SolarSystemFactory::Mercury ||
        planet_or_minor_planet == SolarSystemFactory::Venus) {
      EXPECT_THAT(
          error.separation_per_orbit,
          AllOf(Gt(100 * Milli(ArcSecond)), Lt(200 * Milli(ArcSecond))));
    }
    else {
      EXPECT_THAT(error.separation_per_orbit, Lt(100 * Milli(ArcSecond)));
    }

    if (error.argument_of_periapsis_drift_per_orbit) {
      if (planet_or_minor_planet == SolarSystemFactory::Mercury) {
        // This is what we expect from GR to the last sigfig.
        EXPECT_THAT(
          *error.argument_of_periapsis_drift_per_orbit,
          AllOf(Gt(102 * Milli(ArcSecond)), Lt(104 * Milli(ArcSecond))));
      } else {
        EXPECT_THAT(*error.argument_of_periapsis_drift_per_orbit,
                    Lt(50 * Milli(ArcSecond)));
      }
    }

    EXPECT_THAT(error.inclination_drift_per_orbit, Lt(0.5 * Milli(ArcSecond)));
  }

  for (int const planet_or_minor_planet :
       bodies_orbiting_[SolarSystemFactory::Sun]) {
    if (bodies_orbiting_[planet_or_minor_planet].empty()) {
      continue;
    }
    LOG(INFO) << ">>>>>> Moons of "
              << SolarSystemFactory::name(planet_or_minor_planet);
    for (int const moon : bodies_orbiting_[planet_or_minor_planet]) {
      LOG(INFO) << "=== " << SolarSystemFactory::name(moon);
      auto const error = CompareOrbits(
          moon, *ephemeris, solar_system_at_j2000, twenty_days_later);
      LOG(INFO) << "separation = " << std::fixed
                << error.separation_per_orbit / ArcSecond << u8"″/orbit";
      LOG(INFO) << u8"Δi         = " << std::fixed
                << error.inclination_drift_per_orbit / ArcSecond << u8"″/orbit";
      if (error.longitude_of_ascending_node_drift_per_orbit) {
        LOG(INFO) << u8"ΔΩ         = " << std::fixed
                  << *error.longitude_of_ascending_node_drift_per_orbit /
                         ArcSecond
                  << u8"″/orbit";
      }
      if (error.argument_of_periapsis_drift_per_orbit) {
        LOG(INFO) << u8"Δω         = " << std::fixed
                  << *error.argument_of_periapsis_drift_per_orbit / ArcSecond
                  << u8"″/orbit";
      }
    }
  }
}

TEST_F(SolarSystemDynamicsTest, Спутник1ToСпутник2) {
}

}  // namespace astronomy
}  // namespace principia
<|endoftext|>


<commit_before>#include <iostream>
#include "integration_test_helper.h"
#include "dronecode_sdk.h"
#include "plugins/info/info.h"

using namespace dronecode_sdk;

static void on_discover(uint64_t uuid);
static bool _discovered_system = false;

TEST_F(SitlTest, Info)
{
    DronecodeSDK dc;

    ConnectionResult ret = dc.add_udp_connection();
    ASSERT_EQ(ret, ConnectionResult::SUCCESS);

    dc.register_on_discover(std::bind(&on_discover, std::placeholders::_1));

    while (!_discovered_system) {
        std::cout << "waiting for system to appear..." << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    System &system = dc.system();
    auto info = std::make_shared<Info>(system);

    for (unsigned i = 0; i < 3; ++i) {
        Info::Version version = info->get_version();

        std::cout << "Flight version: " << version.flight_sw_major << "." << version.flight_sw_minor
                  << "." << version.flight_sw_patch << " ("
                  << std::string(version.flight_sw_git_hash) << ")" << std::endl;
        std::cout << "Flight vendor version: " << version.flight_sw_vendor_major << "."
                  << version.flight_sw_vendor_minor << "." << version.flight_sw_vendor_patch
                  << std::endl;
        std::cout << "OS version: " << version.os_sw_major << "." << version.os_sw_minor << "."
                  << version.os_sw_patch << " (" << std::string(version.os_sw_git_hash) << ")"
                  << std::endl;

        EXPECT_NE(version.flight_sw_major, 0);

        // FIXME: This is currently 0.
        // EXPECT_NE(version.os_sw_major, 0);

        Info::Product product = info->get_product();

        std::cout << "Vendor: " << product.vendor_name << std::endl;
        std::cout << "Product: " << product.product_name << std::endl;

        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

void on_discover(uint64_t uuid)
{
    std::cout << "Found system with UUID: " << uuid << std::endl;
    _discovered_system = true;
}
<commit_msg>info: adapt integration test after API changes<commit_after>#include <iostream>
#include "integration_test_helper.h"
#include "dronecode_sdk.h"
#include "plugins/info/info.h"

using namespace dronecode_sdk;

static void on_discover(uint64_t uuid);
static bool _discovered_system = false;

TEST_F(SitlTest, Info)
{
    DronecodeSDK dc;

    ConnectionResult ret = dc.add_udp_connection();
    ASSERT_EQ(ret, ConnectionResult::SUCCESS);

    dc.register_on_discover(std::bind(&on_discover, std::placeholders::_1));

    while (!_discovered_system) {
        std::cout << "waiting for system to appear..." << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    System &system = dc.system();
    auto info = std::make_shared<Info>(system);

    // FIXME: we need to wait some time until Info has determined the version.
    std::this_thread::sleep_for(std::chrono::seconds(1));

    for (unsigned i = 0; i < 3; ++i) {
        std::pair<Info::Result, Info::Version> version_result = info->get_version();

        EXPECT_EQ(version_result.first, Info::Result::SUCCESS);

        if (version_result.first == Info::Result::SUCCESS) {
            std::cout << "Flight version: " << version_result.second.flight_sw_major << "."
                      << version_result.second.flight_sw_minor << "."
                      << version_result.second.flight_sw_patch << " ("
                      << std::string(version_result.second.flight_sw_git_hash) << ")" << std::endl;
            std::cout << "Flight vendor version: " << version_result.second.flight_sw_vendor_major
                      << "." << version_result.second.flight_sw_vendor_minor << "."
                      << version_result.second.flight_sw_vendor_patch << std::endl;
            std::cout << "OS version: " << version_result.second.os_sw_major << "."
                      << version_result.second.os_sw_minor << "."
                      << version_result.second.os_sw_patch << " ("
                      << std::string(version_result.second.os_sw_git_hash) << ")" << std::endl;

            EXPECT_NE(version_result.second.flight_sw_major, 0);

            // FIXME: This is currently 0.
            // EXPECT_NE(version_result.second.os_sw_major, 0);

        } else {
            LogWarn() << "Version request result: " << Info::result_str(version_result.first);
        }

        std::pair<Info::Result, Info::Product> product_result = info->get_product();
        EXPECT_EQ(product_result.first, Info::Result::SUCCESS);

        if (product_result.first == Info::Result::SUCCESS) {
            std::cout << "Vendor: " << product_result.second.vendor_name << std::endl;
            std::cout << "Product: " << product_result.second.product_name << std::endl;
        } else {
            LogWarn() << "Product request result: " << Info::result_str(product_result.first);
        }

        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

void on_discover(uint64_t uuid)
{
    std::cout << "Found system with UUID: " << uuid << std::endl;
    _discovered_system = true;
}
<|endoftext|>