static void
test_less_than()
{
	{
		floating_point_emulation::tfloat<T, S> f(42), g(43);
		BOOST_CHECK_LT(f, g);
	}



	{
		floating_point_emulation::tfloat<T, S> f(42), g(43);
		BOOST_CHECK_EQUAL(f < g, true);
		BOOST_CHECK_EQUAL(g < f, false);
	}

	{
		floating_point_emulation::tfloat<T, S> f(42), g(43.);
		BOOST_CHECK_EQUAL(f < g, true);
		BOOST_CHECK_EQUAL(g < f, false);
	}

	{
		floating_point_emulation::tfloat<T, S> f(42.), g(43);
		BOOST_CHECK_EQUAL(f < g, true);
		BOOST_CHECK_EQUAL(g < f, false);
	}

	{
		floating_point_emulation::tfloat<T, S> f(42.), g(43.);
		BOOST_CHECK_EQUAL(f < g, true);
		BOOST_CHECK_EQUAL(g < f, false);
	}

	{
		floating_point_emulation::tfloat<T, S> f(42), g(42);
		BOOST_CHECK_EQUAL(f < g, false);
		BOOST_CHECK_EQUAL(g < f, false);
	}



	{
		floating_point_emulation::tfloat<T, S> f(42), g(42.);
		BOOST_CHECK_EQUAL(f < g, false);
		BOOST_CHECK_EQUAL(g < f, false);
	}

	{
		floating_point_emulation::tfloat<T, S> f(42.), g(42);
		BOOST_CHECK_EQUAL(f < g, false);
		BOOST_CHECK_EQUAL(g < f, false);
	}

	{
		floating_point_emulation::tfloat<T, S> f(42.), g(42.);
		BOOST_CHECK_EQUAL(f < g, false);
		BOOST_CHECK_EQUAL(g < f, false);
	}
}
示例#2
0
BOOST_AUTO_TEST_CASE_TEMPLATE(test_long_double, Engine, engines)
{
    Engine eng;
    Engine expected;
    for(int i = 0; i < 1000; ++i) {
        long double val = boost::random::generate_canonical<long double, 60>(eng);
        BOOST_CHECK_GE(val, 0);
        BOOST_CHECK_LT(val, 1);
    }
    expected.discard(2000);
    BOOST_CHECK_EQUAL(eng, expected);
    for(int i = 0; i < 1000; ++i) {
        long double val = boost::random::generate_canonical<long double, 12>(eng);
        BOOST_CHECK_GE(val, 0);
        BOOST_CHECK_LT(val, 1);
    }
    expected.discard(1000);
    BOOST_CHECK_EQUAL(eng, expected);
}
示例#3
0
BOOST_AUTO_TEST_CASE_TEMPLATE(test_float, Engine, engines)
{
    Engine eng;
    Engine expected;
    for(int i = 0; i < 1000; ++i) {
        float val = boost::random::generate_canonical<float, 64>(eng);
        BOOST_CHECK_GE(val, 0);
        BOOST_CHECK_LT(val, 1);
    }
    expected.discard(1000);
    BOOST_CHECK_EQUAL(eng, expected);
    for(int i = 0; i < 1000; ++i) {
        float val = boost::random::generate_canonical<float, 12>(eng);
        BOOST_CHECK_GE(val, 0);
        BOOST_CHECK_LT(val, 1);
    }
    expected.discard(1000);
    BOOST_CHECK_EQUAL(eng, expected);
}
示例#4
0
BOOST_FIXTURE_TEST_CASE(CapacityUp, PeriodicalInsertionFixture)
{
  LimitedIo limitedIo;

  ssize_t cap0 = dnl.m_capacity;

  const int RATE = DeadNonceList::INITIAL_CAPACITY * 3;
  this->setRate(RATE);
  limitedIo.defer(LIFETIME * 10);

  ssize_t cap1 = dnl.m_capacity;
  BOOST_CHECK_LT(std::abs(cap1 - RATE), std::abs(cap0 - RATE));
}
示例#5
0
BOOST_FIXTURE_TEST_CASE_TEMPLATE( operator_less_partial_test, F, Fixtures, F )
{
  // for (auto p : F::Plist)
  for (auto it = F::Plist.begin(); it != F::Plist.end(); ++it) {
    auto p = *it;
    for (unsigned k = 0; k<16; k++)
      BOOST_CHECK_EQUAL( p.less_partial(p, k), 0 );
  }
  // for (auto p : F::Plist)
  //   for (auto q : F::Plist)
  for (auto itp = F::Plist.begin(); itp != F::Plist.end(); ++itp) {
    auto p = *itp;
    for (auto itq = F::Plist.begin(); itq != F::Plist.end(); ++itq) {
      auto q = *itq;
      BOOST_CHECK_EQUAL( p.less_partial(q, 0), 0 );
    }
  }

  BOOST_CHECK_EQUAL( F::zero.less_partial(F::P01, 1), 0 );
  BOOST_CHECK_EQUAL( F::P01.less_partial(F::zero, 1), 0 );
  BOOST_CHECK_LT( F::zero.less_partial(F::P01, 2), 0 );
  BOOST_CHECK_GT( F::P01.less_partial(F::zero, 2), 0 );

  BOOST_CHECK_LT( F::zero.less_partial(F::P10, 1), 0 );
  BOOST_CHECK_LT( F::zero.less_partial(F::P10, 2), 0 );
  BOOST_CHECK_GT( F::P10.less_partial(F::zero, 1), 0 );
  BOOST_CHECK_GT( F::P10.less_partial(F::zero, 2), 0 );

  BOOST_CHECK_EQUAL( F::PPa.less_partial(F::PPb, 1), 0 );
  BOOST_CHECK_EQUAL( F::PPa.less_partial(F::PPb, 2), 0 );
  BOOST_CHECK_EQUAL( F::PPa.less_partial(F::PPb, 3), 0 );
  BOOST_CHECK_LT( F::PPa.less_partial(F::PPb, 4), 0 );
  BOOST_CHECK_LT( F::PPa.less_partial(F::PPb, 5), 0 );
  BOOST_CHECK_GT( F::PPb.less_partial(F::PPa, 4), 0 );
  BOOST_CHECK_GT( F::PPb.less_partial(F::PPa, 5), 0 );
}
示例#6
0
BOOST_FIXTURE_TEST_CASE(Whitelist, UdpFactoryMcastFixture)
{
#ifdef __linux__
  // need superuser privileges to create multicast faces on Linux
  SKIP_IF_NOT_SUPERUSER();
#endif // __linux__
  SKIP_IF_UDP_MCAST_NETIF_COUNT_LT(1);

  std::string CONFIG = R"CONFIG(
    face_system
    {
      udp
      {
        whitelist
        {
          ifname %ifname
        }
      }
    }
  )CONFIG";
  boost::replace_first(CONFIG, "%ifname", netifs.front()->getName());

  parseConfig(CONFIG, false);

  auto udpMcastFaces = this->listUdp4McastFaces();
  BOOST_CHECK_LE(udpMcastFaces.size(), 1);
  auto udpMcastFacesV6 = this->listUdp6McastFaces();
  BOOST_CHECK_LE(udpMcastFacesV6.size(), 1);
  udpMcastFaces.insert(udpMcastFaces.end(), udpMcastFacesV6.begin(), udpMcastFacesV6.end());
  BOOST_CHECK_GE(udpMcastFaces.size(), 1);
  BOOST_CHECK(std::all_of(udpMcastFaces.begin(), udpMcastFaces.end(),
                          [this] (const Face* face) { return isFaceOnNetif(*face, *netifs.front()); }));
}

BOOST_FIXTURE_TEST_CASE(Blacklist, UdpFactoryMcastFixture)
{
#ifdef __linux__
  // need superuser privileges to create multicast faces on Linux
  SKIP_IF_NOT_SUPERUSER();
#endif // __linux__
  SKIP_IF_UDP_MCAST_NETIF_COUNT_LT(1);

  std::string CONFIG = R"CONFIG(
    face_system
    {
      udp
      {
        blacklist
        {
          ifname %ifname
        }
      }
    }
  )CONFIG";
  boost::replace_first(CONFIG, "%ifname", netifs.front()->getName());

  parseConfig(CONFIG, false);

  auto udpMcastFaces = this->listUdp4McastFaces();
  if (!netifsV4.empty())
    BOOST_CHECK_GE(udpMcastFaces.size(), netifsV4.size() - 1);
  auto udpMcastFacesV6 = this->listUdp6McastFaces();
  if (!netifsV6.empty())
    BOOST_CHECK_GE(udpMcastFacesV6.size(), netifsV6.size() - 1);
  udpMcastFaces.insert(udpMcastFaces.end(), udpMcastFacesV6.begin(), udpMcastFacesV6.end());
  BOOST_CHECK_LT(udpMcastFaces.size(), netifsV4.size() + netifsV6.size());
  BOOST_CHECK(std::none_of(udpMcastFaces.begin(), udpMcastFaces.end(),
                           [this] (const Face* face) { return isFaceOnNetif(*face, *netifs.front()); }));
}
示例#7
0
BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_lt5, mp_int_type, mp_int_types)
{
  const mp_int_type x("-123456789");
  const mp_int_type y("123456798");
  BOOST_CHECK_LT(x, y);
}
示例#8
0
BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_lt4, mp_int_type, mp_int_types)
{
  const mp_int_type x("-123");
  const mp_int_type y("-10");
  BOOST_CHECK_LT(x, y);
}
示例#9
0
BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_integral_type_lt_mp_int, mp_int_type, mp_int_types)
{
  const mp_int_type x("32101");
  BOOST_CHECK_LT(32100, x);
}
示例#10
0
BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_lt1, mp_int_type, mp_int_types)
{
  const mp_int_type x("12");
  const mp_int_type y("13");
  BOOST_CHECK_LT(x, y);
}
示例#11
0
BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_mp_int_lt_unsigned_integral_type, mp_int_type, mp_int_types)
{
  const mp_int_type x("123456789");
  BOOST_CHECK_LT(x, 123456790U);
}
示例#12
0
BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_mp_int_lt_integral_type4, mp_int_type, mp_int_types)
{
  mp_int_type x(std::numeric_limits<int>::min());
  x -= 1;
  BOOST_CHECK_LT(x, std::numeric_limits<int>::min());
}
示例#13
0
BOOST_AUTO_TEST_CASE_TEMPLATE(cmp_mp_int_lt_integral_type3, mp_int_type, mp_int_types)
{
  const mp_int_type x("-0x100000000");
  BOOST_CHECK_LT(x, -1);
}
	void CDatabaseFixedPointTest::TestCase_FixedPointConstruction()
	{
		CLogger::LogInfo( StringStream() << "**** Start TestCase_FixedPointConstruction ****" );

		int precision = CFixedPoint::GetMaxPrecision() / 2;
		int decimals = precision / 2;
		CLogger::LogInfo( StringStream() << "  From double" );
		{
			CLogger::LogInfo( StringStream() << "    Max Value (Precision overflow)" );
			BOOST_CHECK_THROW( CFixedPoint( std::numeric_limits< double >::max(), precision, decimals ), CDatabaseException );
			CLogger::LogInfo( StringStream() << "    Min Value" );
			BOOST_CHECK_EQUAL( CFixedPoint( std::numeric_limits< double >::min(), precision, decimals ).ToDouble(), 0.0 );
			CLogger::LogInfo( StringStream() << "    Lowest Value (Precision overflow)" );
			BOOST_CHECK_THROW( CFixedPoint( std::numeric_limits< double >::lowest(), precision, decimals ), CDatabaseException );
			CLogger::LogInfo( StringStream() << "    Random valid Value" );
			{
				std::random_device generator;
				double value = fmod( DatabaseUtils::Helpers< EFieldType_FLOAT64 >::GetRandomValue( generator ), 100000.00 );
				CFixedPoint fp( value, precision, decimals );
				BOOST_CHECK_LT( value - fp.ToDouble(), pow( 10, -decimals ) );
			}
		}
		CLogger::LogInfo( StringStream() << "  From float" );
		{
			CLogger::LogInfo( StringStream() << "    Max Value (Precision overflow)" );
			BOOST_CHECK_THROW( CFixedPoint( std::numeric_limits< float >::max(), precision, decimals ), CDatabaseException );
			CLogger::LogInfo( StringStream() << "    Min Value" );
			BOOST_CHECK_EQUAL( CFixedPoint( std::numeric_limits< float >::min(), precision, decimals ).ToDouble(), 0.0 );
			CLogger::LogInfo( StringStream() << "    Lowest Value (Precision overflow)" );
			BOOST_CHECK_THROW( CFixedPoint( std::numeric_limits< float >::lowest(), precision, decimals ), CDatabaseException );
			CLogger::LogInfo( StringStream() << "    Random valid Value" );
			{
				std::random_device generator;
				float value = fmod( DatabaseUtils::Helpers< EFieldType_FLOAT32 >::GetRandomValue( generator ), 100000.00f );
				CFixedPoint fp( value, precision, decimals );
				BOOST_CHECK_LT( value - fp.ToFloat(), pow( 10, -decimals ) );
			}
		}
		CLogger::LogInfo( StringStream() << "  From int32_t" );
		{
			CLogger::LogInfo( StringStream() << "    Max Value" );
			{
				int32_t value = std::numeric_limits< int32_t >::max();
				BOOST_CHECK_EQUAL( CFixedPoint( value, precision, decimals ).ToInt32(), int32_t( value / pow( 10, decimals ) ) );
			}
			CLogger::LogInfo( StringStream() << "    Min Value" );
			{
				int32_t value = std::numeric_limits< int32_t >::min();
				BOOST_CHECK_EQUAL( CFixedPoint( value, precision, decimals ).ToInt32(), int32_t( value / pow( 10, decimals ) ) );
			}
			CLogger::LogInfo( StringStream() << "    Lowest Value" );
			{
				int32_t value = std::numeric_limits< int32_t >::lowest();
				BOOST_CHECK_EQUAL( CFixedPoint( value, precision, decimals ).ToInt32(), int32_t( value / pow( 10, decimals ) ) );
			}
		}
		CLogger::LogInfo( StringStream() << "  From uint32_t" );
		{
			CLogger::LogInfo( StringStream() << "    Max Value" );
			{
				uint32_t value = std::numeric_limits< uint32_t >::max();
				BOOST_CHECK_EQUAL( CFixedPoint( value, precision, decimals ).ToInt32(), uint32_t( value / pow( 10, decimals ) ) );
			}
			CLogger::LogInfo( StringStream() << "    Min Value" );
			{
				uint32_t value = std::numeric_limits< uint32_t >::min();
				BOOST_CHECK_EQUAL( CFixedPoint( value, precision, decimals ).ToInt32(), uint32_t( value / pow( 10, decimals ) ) );
			}
			CLogger::LogInfo( StringStream() << "    Lowest Value" );
			{
				uint32_t value = std::numeric_limits< uint32_t >::lowest();
				BOOST_CHECK_EQUAL( CFixedPoint( value, precision, decimals ).ToInt32(), uint32_t( value / pow( 10, decimals ) ) );
			}
		}
		CLogger::LogInfo( StringStream() << "  From uint64_t" );
		{
			std::random_device generator;
			CLogger::LogInfo( StringStream() << "    Max Value (Precision overflow)" );
			BOOST_CHECK_THROW( CFixedPoint( std::numeric_limits< uint64_t >::max(), precision, decimals ), CDatabaseException );
			CLogger::LogInfo( StringStream() << "    Min Value" );
			BOOST_CHECK_EQUAL( CFixedPoint( std::numeric_limits< uint64_t >::min(), precision, decimals ).ToUInt64(), 0 );
			CLogger::LogInfo( StringStream() << "    Lowest Value" );
			BOOST_CHECK_EQUAL( CFixedPoint( std::numeric_limits< uint64_t >::lowest(), precision, decimals ).ToUInt64(), 0 );
			CLogger::LogInfo( StringStream() << "    Random valid Value" );
			uint64_t value = DatabaseUtils::Helpers< EFieldType_UINT64 >::GetRandomValue( generator ) % uint64_t( pow( 10, precision ) );
			BOOST_CHECK_EQUAL( CFixedPoint( value, precision, decimals ).ToUInt64(), uint64_t( value / pow( 10, decimals ) ) );
		}
		CLogger::LogInfo( StringStream() << "  From String" );
		{
			CLogger::LogInfo( StringStream() << "    Precision overflow in integer value" );
			BOOST_CHECK_THROW( CFixedPoint( STR( "12345678901" ), precision, decimals ), CDatabaseException );
			CLogger::LogInfo( StringStream() << "    Precision overflow in floating point value" );
			BOOST_CHECK_THROW( CFixedPoint( STR( "12345678901.23" ), precision, decimals ), CDatabaseException );
			CLogger::LogInfo( StringStream() << "    Precision overflow, hidden by decimals" );
			BOOST_CHECK_THROW( CFixedPoint( STR( "1234567890" ), precision, decimals ), CDatabaseException );
			CLogger::LogInfo( StringStream() << "    Negative integer Value" );
			BOOST_CHECK_EQUAL( CFixedPoint( STR( "-12345" ), precision, decimals ).ToInt64(), -12345 );
			CLogger::LogInfo( StringStream() << "    Positive integer Value" );
			BOOST_CHECK_EQUAL( CFixedPoint( STR( "12345" ), precision, decimals ).ToInt64(), 12345 );
			CLogger::LogInfo( StringStream() << "    Negative floating point Value" );
			BOOST_CHECK_EQUAL( CFixedPoint( STR( "-12345.6789" ), precision, decimals ).ToDouble(), -12345.6789 );
			CLogger::LogInfo( StringStream() << "    Positive floating point Value, not enough decimals" );
			BOOST_CHECK_EQUAL( CFixedPoint( STR( "12345.6789" ), precision, decimals ).ToDouble(), 12345.6789 );
			CLogger::LogInfo( StringStream() << "    Positive floating point Value, good decimals count" );
			BOOST_CHECK_EQUAL( CFixedPoint( STR( "1234.56789" ), precision, decimals ).ToDouble(), 1234.56789 );
			CLogger::LogInfo( StringStream() << "    Positive floating point Value, more decimals than needed" );
			BOOST_CHECK_EQUAL( CFixedPoint( STR( "123.456789" ), precision, decimals ).ToDouble(), 123.45678 );
		}

		CLogger::LogInfo( StringStream() << "**** End TestCase_FixedPointConstruction ****" );
	}
示例#15
0
BOOST_AUTO_TEST_CASE_TEMPLATE
( test_neighbor_upper_bound, Tp, quad_sets )
{
  typedef quadrance<typename Tp::container_type, int, quad_diff> metric_type;
  typedef typename metric_type::distance_type distance_type;
  typedef neighbor_iterator<typename Tp::container_type, metric_type>
    neighbor_iterator_type;
  // Prove that you can find lower bound with N nodes, down to 1 node
  {
    Tp fix(100, randomize(-20, 20));
    metric_type metric;
    quad target;
    while (!fix.container.empty())
      {
        randomize(-22, 22)(target, 0, 0);
        // Find min and max dist first
        distance_type min_dist;
        distance_type max_dist;
        typename Tp::container_type::iterator it = fix.container.begin();
        min_dist = max_dist
          = metric.distance_to_key(fix.container.rank()(), *it, target);
        ++it;
        for (; it != fix.container.end(); ++it)
          {
            distance_type tmp
              = metric.distance_to_key(fix.container.rank()(), *it, target);
            if (tmp < min_dist) min_dist = tmp;
            if (tmp > max_dist) max_dist = tmp;
          }
        distance_type avg_dist = (min_dist + max_dist) / 2;
        // use this knowledge to test the upper bound
        neighbor_iterator_type i
          = neighbor_upper_bound(fix.container, metric, target, min_dist);
        BOOST_CHECK(i != neighbor_begin(fix.container, metric, target));
        if (i != neighbor_end(fix.container, metric, target))
          { BOOST_CHECK_LT(min_dist, distance(i)); }
        BOOST_CHECK_EQUAL(min_dist, distance(--i));
        i = neighbor_upper_bound(fix.container, metric, target, max_dist);
        BOOST_CHECK(i == neighbor_end(fix.container, metric, target));
        i = neighbor_upper_bound(fix.container, metric, target, avg_dist);
        if (i != neighbor_end(fix.container, metric, target))
          { BOOST_CHECK_GT(distance(i), avg_dist); }
        if (i == neighbor_end(fix.container, metric, target))
          { BOOST_CHECK_LE(distance(--i), avg_dist); }
        fix.container.erase(i);
      }
  }
  // Prove that you can find the upper bound when node and target are same
  {
    Tp fix(100, same());
    metric_type metric;
    quad target;
    same()(target, 0, 100);
    // All points and targets are the same.
    while (!fix.container.empty())
      {
        neighbor_iterator_type i
          = neighbor_upper_bound(fix.container, metric, target, 1);
        BOOST_CHECK(i == neighbor_end(fix.container, metric, target));
        i = neighbor_upper_bound(fix.container, metric, target, 0);
        BOOST_CHECK(i == neighbor_end(fix.container, metric, target));
        fix.container.erase(--i);
      }
  }
  // Prove that you can find the upper bound in an unbalanced tree
  {
    Tp fix(100, increase());
    metric_type metric;
    quad target;
    while (!fix.container.empty())
      {
        randomize(0, 100)(target, 0, 0);
        // Find min and max dist first
        distance_type min_dist;
        distance_type max_dist;
        typename Tp::container_type::iterator it = fix.container.begin();
        min_dist = max_dist
          = metric.distance_to_key(fix.container.rank()(), *it, target);
        ++it;
        for (; it != fix.container.end(); ++it)
          {
            distance_type tmp
              = metric.distance_to_key(fix.container.rank()(), *it, target);
            if (tmp < min_dist) min_dist = tmp;
            if (tmp > max_dist) max_dist = tmp;
          }
        distance_type avg_dist = (min_dist + max_dist) / 2;
        // Use this knowledge to test the upper bound
        neighbor_iterator_type i
          = neighbor_upper_bound(fix.container, metric, target, min_dist);
        BOOST_CHECK(i != neighbor_begin(fix.container, metric, target));
        if (i != neighbor_end(fix.container, metric, target))
          { BOOST_CHECK_LT(min_dist, distance(i)); }
        BOOST_CHECK_EQUAL(min_dist, distance(--i));
        i = neighbor_upper_bound(fix.container, metric, target, max_dist);
        BOOST_CHECK(i == neighbor_end(fix.container, metric, target));
        i = neighbor_upper_bound(fix.container, metric, target, avg_dist);
        if (i != neighbor_end(fix.container, metric, target))
          { BOOST_CHECK_GT(distance(i), avg_dist); }
        if (i == neighbor_end(fix.container, metric, target))
          { BOOST_CHECK_LE(distance(--i), avg_dist); }
        fix.container.erase(i);
      }
  }
  // Prove that you can find the upper bound in an unbalanced tree
  {
    Tp fix(100, decrease());
    metric_type metric;
    quad target;
    while (!fix.container.empty())
      {
        randomize(0, 100)(target, 0, 0);
        // Find min and max dist first
        distance_type min_dist;
        distance_type max_dist;
        typename Tp::container_type::iterator it = fix.container.begin();
        min_dist = max_dist
          = metric.distance_to_key(fix.container.rank()(), *it, target);
        ++it;
        for (; it != fix.container.end(); ++it)
          {
            distance_type tmp
              = metric.distance_to_key(fix.container.rank()(), *it, target);
            if (tmp < min_dist) min_dist = tmp;
            if (tmp > max_dist) max_dist = tmp;
          }
        distance_type avg_dist = (min_dist + max_dist) / 2;
        // Use this knowledge to test the upper bound
        neighbor_iterator_type i
          = neighbor_upper_bound(fix.container, metric, target, min_dist);
        BOOST_CHECK(i != neighbor_begin(fix.container, metric, target));
        if (i != neighbor_end(fix.container, metric, target))
          { BOOST_CHECK_LT(min_dist, distance(i)); }
        BOOST_CHECK_EQUAL(min_dist, distance(--i));
        i = neighbor_upper_bound(fix.container, metric, target, max_dist);
        BOOST_CHECK(i == neighbor_end(fix.container, metric, target));
        i = neighbor_upper_bound(fix.container, metric, target, avg_dist);
        if (i != neighbor_end(fix.container, metric, target))
          { BOOST_CHECK_GT(distance(i), avg_dist); }
        if (i == neighbor_end(fix.container, metric, target))
          { BOOST_CHECK_LE(distance(--i), avg_dist); }
        fix.container.erase(i);
      }
  }
}
示例#16
0
BOOST_AUTO_TEST_CASE(TestProjectile, DATA_TEST_PREDICATE) {
    {
        auto character = Global::get().e->createPedestrian(1, {25.f, 0.f, 0.f});
        BOOST_REQUIRE(character != nullptr);

        auto wepdata = &Global::get().e->data->weaponData.at(5);

        auto projectile = new ProjectileObject(
            Global::get().e, {26.f, 1.f, 10.f},
            {ProjectileObject::Grenade, {0.f, 0.f, -1.f}, 2.0f, 5.0f, wepdata});

        Global::get().e->allObjects.push_back(projectile);

        BOOST_CHECK(character->getCurrentState().health == 100.f);

        for (float t = 0.f; t <= 5.f; t += 0.016f) {
            Global::get().e->dynamicsWorld->stepSimulation(0.016f, 0, 0);
            projectile->tick(0.016f);
        }

        BOOST_CHECK_LT(
            glm::distance(character->getPosition(), projectile->getPosition()),
            10.f);
        BOOST_CHECK_LT(
            glm::distance(character->getPosition(), projectile->getPosition()),
            5.f);

        // Grenade should have dentonated by this point
        BOOST_CHECK(character->getCurrentState().health < 100.f);

        Global::get().e->destroyObjectQueued(character);
        Global::get().e->destroyQueuedObjects();
    }

    {
        auto character = Global::get().e->createPedestrian(1, {25.f, 0.f, 0.f});
        BOOST_REQUIRE(character != nullptr);

        auto wepdata = &Global::get().e->data->weaponData.at(6);

        auto projectile = new ProjectileObject(
            Global::get().e, {26.f, 1.f, 10.f},
            {ProjectileObject::Molotov, {0.f, 0.f, -1.f}, 2.0f, 10.f, wepdata});

        Global::get().e->allObjects.push_back(projectile);

        BOOST_CHECK(character->getCurrentState().health == 100.f);

        for (float t = 0.f; t <= 9.0f; t += 0.016f) {
            Global::get().e->dynamicsWorld->stepSimulation(0.016f, 0, 0);
            projectile->tick(0.016f);
        }

        BOOST_CHECK(projectile->getPosition().z < 10.f);
        BOOST_CHECK(projectile->getPosition().z > 0.f);

        BOOST_CHECK(character->getCurrentState().health < 100.f);

        Global::get().e->destroyObjectQueued(character);
        Global::get().e->destroyQueuedObjects();
    }
    {
        auto character = Global::get().e->createPedestrian(1, {25.f, 0.f, 0.f});
        BOOST_REQUIRE(character != nullptr);

        auto wepdata = &Global::get().e->data->weaponData.at(7);

        auto projectile = new ProjectileObject(
            Global::get().e, {26.f, 1.f, 10.f},
            {ProjectileObject::RPG, {0.f, 0.f, -1.f}, 2.0f, 10.f, wepdata});

        Global::get().e->allObjects.push_back(projectile);

        BOOST_CHECK(character->getCurrentState().health == 100.f);

        for (float t = 0.f; t <= 9.f; t += 0.016f) {
            Global::get().e->dynamicsWorld->stepSimulation(0.016f, 0, 0);
            projectile->tick(0.016f);
        }

        BOOST_CHECK(projectile->getPosition().z < 10.f);

        BOOST_CHECK(character->getCurrentState().health < 100.f);

        Global::get().e->destroyObjectQueued(character);
        Global::get().e->destroyQueuedObjects();
    }
}