<commit_before>/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          https://www.mrpt.org/                         |
   |                                                                        |
   | Copyright (c) 2005-2021, Individual contributors, see AUTHORS file     |
   | See: https://www.mrpt.org/Authors - All rights reserved.               |
   | Released under BSD License. See: https://www.mrpt.org/License          |
   +------------------------------------------------------------------------+ */

#include "core-precomp.h"  // Precompiled headers
//
#include <mrpt/core/exceptions.h>

namespace mrpt::internal
{
std::string exception_line_msg(
	const std::string_view& msg, const char* filename, unsigned int line,
	const char* function_name)
{
	std::string s;
	s += filename;
	s += ":";
	s += std::to_string(line);
	s += ": [";
	s += function_name;
	s += "] ";
	s += msg;
	s += "\n";
	return s;
}

static size_t findClosingBracket(
	const char chClosing, const char chOpening, const std::string& str)
{
	const size_t N = str.size();
	int nestedLevel = 0;
	for (size_t p = 0; p < N; p++)
	{
		if (str[p] == chClosing)
		{
			if (nestedLevel == 1) return p;
			nestedLevel--;
		}
		else if (str[p] == chOpening)
			nestedLevel++;
	}
	return std::string::npos;
}

/** Recursive implementation for mrpt::exception_to_str() */
void impl_excep_to_str(
	const std::exception& e, std::string& ret, [[maybe_unused]] int lvl = 0)
{
#if defined(MRPT_EXCEPTIONS_WITH_CALL_STACK)
	using namespace std::string_literals;
	try
	{
		std::rethrow_if_nested(e);
		// We traversed the entire call stack,
		// show just the original error message: "file:line: [func] MSG"

		if (const auto* ecb =
				dynamic_cast<const ExceptionWithCallBackBase*>(&e);
			ecb != nullptr)
		{
			std::string err = ecb->originalWhat;
			if (!err.empty() && *err.rbegin() != '\n') err += "\n"s;

			if (const auto idx = findClosingBracket(']', '[', err);
				idx != std::string::npos)
			{
				err = "Message: "s + err.substr(idx + 1) + "Location: "s +
					err.substr(0, idx) + "\n"s;
			}

			ret += "==== MRPT exception ====\n";
			ret += err;
			ret += "Call stack backtrace:\n";
			ret += ecb->callStack.asString();
		}
		else
		{
			ret = "==== non-MRPT exception ====\n";
			ret += e.what();
			ret += "\n";
		}
	}
	catch (const std::exception& er)
	{
		// It's nested: recursive call
		if (lvl < MRPT_EXCEPTIONS_CALL_STACK_MAX_DEPTH)
			impl_excep_to_str(er, ret, lvl + 1);
		else
		{
			ret += " (... max depth reached ...)\n";
		}
	}
#else
	// Basic version:
	const auto* ecb = dynamic_cast<const ExceptionWithCallBackBase*>(&e);
	if(ecb)
	{
		ret = ecb->originalWhat;
	}
	else
	{
		ret = e.what();
	}
#endif
}
}  // namespace mrpt::internal

std::string mrpt::exception_to_str(const std::exception& e)
{
	std::string descr;
	mrpt::internal::impl_excep_to_str(e, descr);
	return descr;
}

int mrpt::internal::MAX_BACKTRACE_DEPTH()
{
	return MRPT_EXCEPTIONS_CALL_STACK_MAX_DEPTH;
}
<commit_msg>fix clang-format-10<commit_after>/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          https://www.mrpt.org/                         |
   |                                                                        |
   | Copyright (c) 2005-2021, Individual contributors, see AUTHORS file     |
   | See: https://www.mrpt.org/Authors - All rights reserved.               |
   | Released under BSD License. See: https://www.mrpt.org/License          |
   +------------------------------------------------------------------------+ */

#include "core-precomp.h"  // Precompiled headers
//
#include <mrpt/core/exceptions.h>

namespace mrpt::internal
{
std::string exception_line_msg(
	const std::string_view& msg, const char* filename, unsigned int line,
	const char* function_name)
{
	std::string s;
	s += filename;
	s += ":";
	s += std::to_string(line);
	s += ": [";
	s += function_name;
	s += "] ";
	s += msg;
	s += "\n";
	return s;
}

static size_t findClosingBracket(
	const char chClosing, const char chOpening, const std::string& str)
{
	const size_t N = str.size();
	int nestedLevel = 0;
	for (size_t p = 0; p < N; p++)
	{
		if (str[p] == chClosing)
		{
			if (nestedLevel == 1) return p;
			nestedLevel--;
		}
		else if (str[p] == chOpening)
			nestedLevel++;
	}
	return std::string::npos;
}

/** Recursive implementation for mrpt::exception_to_str() */
void impl_excep_to_str(
	const std::exception& e, std::string& ret, [[maybe_unused]] int lvl = 0)
{
#if defined(MRPT_EXCEPTIONS_WITH_CALL_STACK)
	using namespace std::string_literals;
	try
	{
		std::rethrow_if_nested(e);
		// We traversed the entire call stack,
		// show just the original error message: "file:line: [func] MSG"

		if (const auto* ecb =
				dynamic_cast<const ExceptionWithCallBackBase*>(&e);
			ecb != nullptr)
		{
			std::string err = ecb->originalWhat;
			if (!err.empty() && *err.rbegin() != '\n') err += "\n"s;

			if (const auto idx = findClosingBracket(']', '[', err);
				idx != std::string::npos)
			{
				err = "Message: "s + err.substr(idx + 1) + "Location: "s +
					err.substr(0, idx) + "\n"s;
			}

			ret += "==== MRPT exception ====\n";
			ret += err;
			ret += "Call stack backtrace:\n";
			ret += ecb->callStack.asString();
		}
		else
		{
			ret = "==== non-MRPT exception ====\n";
			ret += e.what();
			ret += "\n";
		}
	}
	catch (const std::exception& er)
	{
		// It's nested: recursive call
		if (lvl < MRPT_EXCEPTIONS_CALL_STACK_MAX_DEPTH)
			impl_excep_to_str(er, ret, lvl + 1);
		else
		{
			ret += " (... max depth reached ...)\n";
		}
	}
#else
	// Basic version:
	const auto* ecb = dynamic_cast<const ExceptionWithCallBackBase*>(&e);
	if (ecb) { ret = ecb->originalWhat; }
	else
	{
		ret = e.what();
	}
#endif
}
}  // namespace mrpt::internal

std::string mrpt::exception_to_str(const std::exception& e)
{
	std::string descr;
	mrpt::internal::impl_excep_to_str(e, descr);
	return descr;
}

int mrpt::internal::MAX_BACKTRACE_DEPTH()
{
	return MRPT_EXCEPTIONS_CALL_STACK_MAX_DEPTH;
}
<|endoftext|>


<commit_before><commit_msg>gltfio: Fix animation by clamping the per-channel interpolant.<commit_after><|endoftext|>


<commit_before>// SimpleVehicle.cc
//  Currently, this a do-nothing module at confirms the interface is working.
//  It is intended to be a model of a simple object.
//

#include <iostream>
#include <cmath>

#include "Scenario.h"
#include "models/SimpleMotion.h"

using std::string;
// using vecmath::Cart3f;

class SimpleFlight : public Scenario {
  protected:

  public:
    void initcond();
    AeroForces getAeroForces(float density, float mach, float attack);

    const char* getName() { return "SimpleFlight"; }
    SimpleMotionState* getSimpleMotion();

  private:

};

// Initial conditions
void
SimpleFlight::initcond()
{
    // Need to decide this...
}

AeroForces
SimpleFlight::getAeroForces(float density, float mach, float attack)
{
    // should return following:  lift force, drag force, rotational speed
    AeroForces af;
    af.lift = 4.0;
    af.drag = 1.0;
    af.rotate = 0.0;

    return af;
}

SimpleMotionState*
SimpleFlight::getSimpleMotion()
{
    SimpleMotionState* motion_st = (SimpleMotionState*)0;
    // This is a dangling value; how is it computed...
    return motion_st;
}

// class factories
extern "C" Scenario* create() { return new SimpleFlight; }
extern "C" void destroy(Scenario* s) { delete s; }

<commit_msg>Expand SimpleFlight to more realistic scenario. Falling body with data logging of trajectory and atmospheric conditions.<commit_after>// SimpleVehicle.cc
//  This is a simple module that confirms that the dynamic loading
//  interface is working.
//

#include <iostream>
#include <cmath>

#include "Scenario.h"
#include "models/SimpleMotion.h"

using std::string;
using std::abs;
#ifdef SIMPLEFLIGHT_DEBUG
using std::cout;
using std::endl;
#endif // SIMPLEFLIGHT_DEBUG

// output flags; match with SimEngine.cc
#define PUT_TRAJ        0x0001
#define PUT_AERO        0x0002
#define PUT_ATMOS       0x0100
#define PUT_GRAV        0x0200

#define STATEMAX        2
class SimpleFlight : public Scenario {
  protected:
    SimpleMotionState motionstate[STATEMAX];
    int currstate;

  public:
    void initcond();
    AeroForces getAeroForces(float density, float mach, float attack);

    const char* getName() { return "SimpleFlight"; }
    SimpleMotionState* getSimpleMotion();
    bool moresteps();
    unsigned int putnow(unsigned int forcemask = 0);

  private:

    // threshhold limits on run
    float tlimit;       // max time limit (want t<= tlimit)
    float hlimit;       // min height limit (want h >= hlimit)

    // output throttler
    float put_tnext;    // time
    float put_tintv;    // time interval
    float put_hatmos;   // atmos report height
};

//  This code implements a simple of model of a falling body.
//  For simplicity, this can be imagined with the following initial
//  conditions:
//    * 10,000 meters above the reference surface.
//    * initial horizontal motion of 10 meters/sec.
//    * constant downward gravity of 10 meters/(sec^2).
//  Computation happens at 1 second intervals, and ends when either:
//    * 100 seconds have elapsed, or
//    * the body is within 1,000 meters of the surface.
//  Crude accuracy is provided at 1 second. Try 0.5 or 0.02 for more
//  interesting results.
//
void
SimpleFlight::initcond()
{
    currstate = 0;
    SimpleMotionState& ms = motionstate[currstate];

    tlimit = 100.0;
    hlimit = 1000.0;
    ms.x = Cart3f(0.0, 0.0, 10000.0);
    ms.dx = Cart3f(10.0, 0.0, 0.0);
    ms.ddx = Cart3f(0.0, 0.0, -9.8);
    ms.dt = 1.0;        // step-size
    put_tnext = 0.0;    // next scheduled put
    put_tintv = 5.0;    // interval
    put_hatmos = -10000.0;     // atmos report height; force first report
}

bool
SimpleFlight::moresteps()
{
    SimpleMotionState& ms = motionstate[currstate];
    bool moretime = ms.t <= tlimit;
    bool moreheight = ms.x[2] >= hlimit;

    return moretime && moreheight;
}

SimpleMotionState*
SimpleFlight::getSimpleMotion()
{
    int newstate = (currstate+1) % STATEMAX;
#ifdef SIMPLEFLIGHT_DEBUG
    cout << "newstate" << newstate << endl;
#endif // SIMPLEFLIGHT_DEBUG

    SimpleMotionState& cms = motionstate[currstate];
    SimpleMotionState& nms = motionstate[newstate];

    nms.ddx = cms.ddx;          // constant acceleration
    nms.dt = cms.dt;            // constant step-size
    nms.dx = cms.dx + nms.ddx * nms.dt;
    nms.x = cms.x + nms.dx * nms.dt;
    nms.t = cms.t + nms.dt;

    currstate = newstate;
    return &nms;
}

unsigned int
SimpleFlight::putnow(unsigned int forcemask)
{
    unsigned int put_flags = 0;
    SimpleMotionState& cms = motionstate[currstate];

    if (forcemask) {
        put_flags = forcemask;
    }

    if (cms.t > put_tnext) {
        put_flags |= PUT_TRAJ;
        put_tnext += put_tintv;
    }

    if (abs(cms.x[2] - put_hatmos) > 1000.0) {
        put_flags |= PUT_ATMOS;
        put_hatmos = cms.x[2];
    }

    return put_flags;
}

// class factories
extern "C" Scenario* create() { return new SimpleFlight; }
extern "C" void destroy(Scenario* s) { delete s; }

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2011-2012 Morwenn
 *
 * static_math 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.
 *
 * static_math is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <static_math/complex.h>

using namespace smath;

int main()
{
    // Can't really do unit tests with floating point numbers

    return 0;
}
<commit_msg>First tests.<commit_after>/*
 * Copyright (C) 2011-2012 Morwenn
 *
 * static_math 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.
 *
 * static_math is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <static_math/utils/compare.h>
#include <static_math/complex.h>

using namespace smath;

int main()
{
    // Constructor tests
    constexpr auto i1 = imaginary<float>(5.8f);
    static_assert(equals(i1.value(), 5.8f), "");

    constexpr auto c1 = complex<float>(1.2f, 2.5f);
    static_assert(equals(c1.real(), 1.2f), "");
    static_assert(equals(c1.imag_value(), 2.5f), "");

    return 0;
}
<|endoftext|>


<commit_before>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "mojo/public/cpp/bindings/interface_ptr.h"
#include "mojo/public/cpp/environment/environment.h"
#include "mojo/public/cpp/test_support/test_support.h"
#include "mojo/public/cpp/utility/run_loop.h"
#include "mojo/public/interfaces/bindings/tests/binding_callback_test_interfaces.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"

///////////////////////////////////////////////////////////////////////////////
//
// The tests in this file are designed to test the interaction between a
// Callback and its associated Binding. If a Callback is deleted before
// being used we DCHECK fail--unless the associated Binding has already
// been closed or deleted. This contract must be explained to the Mojo
// application developer. For example it is the developer's responsibility to
// ensure that the Binding is destroyed before an unused Callback is destroyed.
//
///////////////////////////////////////////////////////////////////////////////

namespace mojo {
namespace test {
namespace {

// A Runnable object that saves the last value it sees via the
// provided int32_t*. Used on the client side.
class ValueSaver {
 public:
  explicit ValueSaver(int32_t* last_value_seen)
      : last_value_seen_(last_value_seen) {}
  void Run(int32_t x) const { *last_value_seen_ = x; }

 private:
  int32_t* const last_value_seen_;
};

// An implementation of BindingCallbackTestInterface used on the server side.
// All it does is save the values and Callbacks it sees.
class BindingCallbackTestInterfaceImpl : public BindingCallbackTestInterface {
 public:
  BindingCallbackTestInterfaceImpl()
      : last_server_value_seen_(0),
        callback_saved_(new Callback<void(int32_t)>()) {}

  ~BindingCallbackTestInterfaceImpl() override {
    if (callback_saved_) {
      delete callback_saved_;
    }
  }

  // Run's the callback previously saved from the last invocation
  // of |EchoInt()|.
  bool RunCallback() {
    if (callback_saved_) {
      callback_saved_->Run(last_server_value_seen_);
      return true;
    }
    return false;
  }

  // Delete's the previously saved callback.
  void DeleteCallback() {
    delete callback_saved_;
    callback_saved_ = nullptr;
  }

  // Saves its two input values in member variables and does nothing else.
  void EchoInt(int32_t x, const Callback<void(int32_t)>& callback) {
    last_server_value_seen_ = x;
    *callback_saved_ = callback;
  }

  void resetLastServerValueSeen() { last_server_value_seen_ = 0; }

  int32_t last_server_value_seen() const { return last_server_value_seen_; }

 private:
  int32_t last_server_value_seen_;
  Callback<void(int32_t)>* callback_saved_;
};

class BindingCallbackTest : public testing::Test {
 public:
  ~BindingCallbackTest() override {}

 protected:
  int32_t last_client_callback_value_seen_;
  ScopedMessagePipeHandle handle_client_;
  ScopedMessagePipeHandle handle_server_;
  BindingCallbackTestInterfacePtr interface_ptr_;

  void PumpMessages() { loop_.RunUntilIdle(); }
  void SetUp() {
    CreateMessagePipe(nullptr, &handle_client_, &handle_server_);
    // Create the client InterfacePtr.
    interface_ptr_ =
        MakeProxy<BindingCallbackTestInterface>(handle_client_.Pass());
  }

 private:
  Environment env_;
  RunLoop loop_;
};

// Tests that the InterfacePtr and the Binding can communicate with each
// other normally.
TEST_F(BindingCallbackTest, Basic) {
  // Create the ServerImpl and the Binding.
  BindingCallbackTestInterfaceImpl server_impl;
  Binding<BindingCallbackTestInterface> binding(
      &server_impl,
      MakeRequest<BindingCallbackTestInterface>(handle_server_.Pass()));

  // Initialize the test values.
  server_impl.resetLastServerValueSeen();
  last_client_callback_value_seen_ = 0;

  // Invoke the Echo method.
  interface_ptr_->EchoInt(7, ValueSaver(&last_client_callback_value_seen_));
  PumpMessages();

  // Check that server saw the correct value, but the client has not yet.
  EXPECT_EQ(7, server_impl.last_server_value_seen());
  EXPECT_EQ(0, last_client_callback_value_seen_);

  // Now run the Callback.
  server_impl.RunCallback();
  PumpMessages();

  // Check that the client has now seen the correct value.
  EXPECT_EQ(7, last_client_callback_value_seen_);

  // Initialize the test values again.
  server_impl.resetLastServerValueSeen();
  last_client_callback_value_seen_ = 0;

  // Invoke the Echo method again.
  interface_ptr_->EchoInt(13, ValueSaver(&last_client_callback_value_seen_));
  PumpMessages();

  // Check that server saw the correct value, but the client has not yet.
  EXPECT_EQ(13, server_impl.last_server_value_seen());
  EXPECT_EQ(0, last_client_callback_value_seen_);

  // Now run the Callback again.
  server_impl.RunCallback();
  PumpMessages();

  // Check that the client has now seen the correct value again.
  EXPECT_EQ(13, last_client_callback_value_seen_);
}

// Tests that running the Callback after the Binding has been deleted
// results in a clean failure.
TEST_F(BindingCallbackTest, DeleteBindingThenRunCallback) {
  // Create the ServerImpl.
  BindingCallbackTestInterfaceImpl server_impl;
  {
    // Create the binding in an inner scope so it can be deleted first.
    Binding<BindingCallbackTestInterface> binding(
        &server_impl,
        MakeRequest<BindingCallbackTestInterface>(handle_server_.Pass()));

    // Initialize the test values.
    server_impl.resetLastServerValueSeen();
    last_client_callback_value_seen_ = 0;

    // Invoke the Echo method.
    interface_ptr_->EchoInt(7, ValueSaver(&last_client_callback_value_seen_));
    PumpMessages();
  }
  // The binding has now been destroyed and the pipe is closed.

  // Check that server saw the correct value, but the client has not yet.
  EXPECT_EQ(7, server_impl.last_server_value_seen());
  EXPECT_EQ(0, last_client_callback_value_seen_);

  // Now try to run the Callback. This should do nothing since the pipe
  // is closed.
  EXPECT_TRUE(server_impl.RunCallback());
  PumpMessages();

  // Check that the client has still not seen the correct value.
  EXPECT_EQ(0, last_client_callback_value_seen_);

  // Attempt to invoke the method again and confirm that an error was
  // encountered.
  interface_ptr_->EchoInt(13, ValueSaver(&last_client_callback_value_seen_));
  PumpMessages();
  EXPECT_TRUE(interface_ptr_.encountered_error());
}

// Tests that deleting a Callback without running it after the corresponding
// binding has already been deleted does not result in a crash.
TEST_F(BindingCallbackTest, DeleteBindingThenDeleteCallback) {
  // Create the ServerImpl.
  BindingCallbackTestInterfaceImpl server_impl;
  {
    // Create the binding in an inner scope so it can be deleted first.
    Binding<BindingCallbackTestInterface> binding(
        &server_impl,
        MakeRequest<BindingCallbackTestInterface>(handle_server_.Pass()));

    // Initialize the test values.
    server_impl.resetLastServerValueSeen();
    last_client_callback_value_seen_ = 0;

    // Invoke the Echo method.
    interface_ptr_->EchoInt(7, ValueSaver(&last_client_callback_value_seen_));
    PumpMessages();
  }
  // The binding has now been destroyed and the pipe is closed.

  // Check that server saw the correct value, but the client has not yet.
  EXPECT_EQ(7, server_impl.last_server_value_seen());
  EXPECT_EQ(0, last_client_callback_value_seen_);

  // Delete the callback without running it. This should not
  // cause a problem because the insfrastructure can detect that the
  // binding has already been destroyed and the pipe is closed.
  server_impl.DeleteCallback();
}

// Tests that closing a Binding allows us to delete a callback
// without running it without encountering a crash.
TEST_F(BindingCallbackTest, CloseBindingBeforeDeletingCallback) {
  // Create the ServerImpl and the Binding.
  BindingCallbackTestInterfaceImpl server_impl;
  Binding<BindingCallbackTestInterface> binding(
      &server_impl,
      MakeRequest<BindingCallbackTestInterface>(handle_server_.Pass()));

  // Initialize the test values.
  server_impl.resetLastServerValueSeen();
  last_client_callback_value_seen_ = 0;

  // Invoke the Echo method.
  interface_ptr_->EchoInt(7, ValueSaver(&last_client_callback_value_seen_));
  PumpMessages();

  // Check that server saw the correct value, but the client has not yet.
  EXPECT_EQ(7, server_impl.last_server_value_seen());
  EXPECT_EQ(0, last_client_callback_value_seen_);

  // Now close the Binding.
  binding.Close();

  // Delete the callback without running it. This should not
  // cause a crash because the insfrastructure can detect that the
  // binding has already been closed.
  server_impl.DeleteCallback();

  // Check that the client has still not seen the correct value.
  EXPECT_EQ(0, last_client_callback_value_seen_);
}

// Tests that deleting a Callback without using it before the
// Binding has been destroyed or closed results in a DCHECK.
TEST_F(BindingCallbackTest, DeleteCallbackBeforeBindingDeathTest) {
  // Create the ServerImpl and the Binding.
  BindingCallbackTestInterfaceImpl server_impl;
  Binding<BindingCallbackTestInterface> binding(
      &server_impl,
      MakeRequest<BindingCallbackTestInterface>(handle_server_.Pass()));

  // Initialize the test values.
  server_impl.resetLastServerValueSeen();
  last_client_callback_value_seen_ = 0;

  // Invoke the Echo method.
  interface_ptr_->EchoInt(7, ValueSaver(&last_client_callback_value_seen_));
  PumpMessages();

  // Check that server saw the correct value, but the client has not yet.
  EXPECT_EQ(7, server_impl.last_server_value_seen());
  EXPECT_EQ(0, last_client_callback_value_seen_);

  // Delete the callback without running it. This should cause a crash
  // due to a DCHECK.
  EXPECT_DEATH(server_impl.DeleteCallback(),
               "Check failed: !callback_was_dropped.");
}

}  // namespace
}  // namespace test
}  // namespace mojo
<commit_msg>Fixes test broken in release builds: Add #ifdef DEBUG before EXPECT_DEATH.<commit_after>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "mojo/public/cpp/bindings/interface_ptr.h"
#include "mojo/public/cpp/environment/environment.h"
#include "mojo/public/cpp/test_support/test_support.h"
#include "mojo/public/cpp/utility/run_loop.h"
#include "mojo/public/interfaces/bindings/tests/binding_callback_test_interfaces.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"

///////////////////////////////////////////////////////////////////////////////
//
// The tests in this file are designed to test the interaction between a
// Callback and its associated Binding. If a Callback is deleted before
// being used we DCHECK fail--unless the associated Binding has already
// been closed or deleted. This contract must be explained to the Mojo
// application developer. For example it is the developer's responsibility to
// ensure that the Binding is destroyed before an unused Callback is destroyed.
//
///////////////////////////////////////////////////////////////////////////////

namespace mojo {
namespace test {
namespace {

// A Runnable object that saves the last value it sees via the
// provided int32_t*. Used on the client side.
class ValueSaver {
 public:
  explicit ValueSaver(int32_t* last_value_seen)
      : last_value_seen_(last_value_seen) {}
  void Run(int32_t x) const { *last_value_seen_ = x; }

 private:
  int32_t* const last_value_seen_;
};

// An implementation of BindingCallbackTestInterface used on the server side.
// All it does is save the values and Callbacks it sees.
class BindingCallbackTestInterfaceImpl : public BindingCallbackTestInterface {
 public:
  BindingCallbackTestInterfaceImpl()
      : last_server_value_seen_(0),
        callback_saved_(new Callback<void(int32_t)>()) {}

  ~BindingCallbackTestInterfaceImpl() override {
    if (callback_saved_) {
      delete callback_saved_;
    }
  }

  // Run's the callback previously saved from the last invocation
  // of |EchoInt()|.
  bool RunCallback() {
    if (callback_saved_) {
      callback_saved_->Run(last_server_value_seen_);
      return true;
    }
    return false;
  }

  // Delete's the previously saved callback.
  void DeleteCallback() {
    delete callback_saved_;
    callback_saved_ = nullptr;
  }

  // Saves its two input values in member variables and does nothing else.
  void EchoInt(int32_t x, const Callback<void(int32_t)>& callback) {
    last_server_value_seen_ = x;
    *callback_saved_ = callback;
  }

  void resetLastServerValueSeen() { last_server_value_seen_ = 0; }

  int32_t last_server_value_seen() const { return last_server_value_seen_; }

 private:
  int32_t last_server_value_seen_;
  Callback<void(int32_t)>* callback_saved_;
};

class BindingCallbackTest : public testing::Test {
 public:
  ~BindingCallbackTest() override {}

 protected:
  int32_t last_client_callback_value_seen_;
  ScopedMessagePipeHandle handle_client_;
  ScopedMessagePipeHandle handle_server_;
  BindingCallbackTestInterfacePtr interface_ptr_;

  void PumpMessages() { loop_.RunUntilIdle(); }
  void SetUp() {
    CreateMessagePipe(nullptr, &handle_client_, &handle_server_);
    // Create the client InterfacePtr.
    interface_ptr_ =
        MakeProxy<BindingCallbackTestInterface>(handle_client_.Pass());
  }

 private:
  Environment env_;
  RunLoop loop_;
};

// Tests that the InterfacePtr and the Binding can communicate with each
// other normally.
TEST_F(BindingCallbackTest, Basic) {
  // Create the ServerImpl and the Binding.
  BindingCallbackTestInterfaceImpl server_impl;
  Binding<BindingCallbackTestInterface> binding(
      &server_impl,
      MakeRequest<BindingCallbackTestInterface>(handle_server_.Pass()));

  // Initialize the test values.
  server_impl.resetLastServerValueSeen();
  last_client_callback_value_seen_ = 0;

  // Invoke the Echo method.
  interface_ptr_->EchoInt(7, ValueSaver(&last_client_callback_value_seen_));
  PumpMessages();

  // Check that server saw the correct value, but the client has not yet.
  EXPECT_EQ(7, server_impl.last_server_value_seen());
  EXPECT_EQ(0, last_client_callback_value_seen_);

  // Now run the Callback.
  server_impl.RunCallback();
  PumpMessages();

  // Check that the client has now seen the correct value.
  EXPECT_EQ(7, last_client_callback_value_seen_);

  // Initialize the test values again.
  server_impl.resetLastServerValueSeen();
  last_client_callback_value_seen_ = 0;

  // Invoke the Echo method again.
  interface_ptr_->EchoInt(13, ValueSaver(&last_client_callback_value_seen_));
  PumpMessages();

  // Check that server saw the correct value, but the client has not yet.
  EXPECT_EQ(13, server_impl.last_server_value_seen());
  EXPECT_EQ(0, last_client_callback_value_seen_);

  // Now run the Callback again.
  server_impl.RunCallback();
  PumpMessages();

  // Check that the client has now seen the correct value again.
  EXPECT_EQ(13, last_client_callback_value_seen_);
}

// Tests that running the Callback after the Binding has been deleted
// results in a clean failure.
TEST_F(BindingCallbackTest, DeleteBindingThenRunCallback) {
  // Create the ServerImpl.
  BindingCallbackTestInterfaceImpl server_impl;
  {
    // Create the binding in an inner scope so it can be deleted first.
    Binding<BindingCallbackTestInterface> binding(
        &server_impl,
        MakeRequest<BindingCallbackTestInterface>(handle_server_.Pass()));

    // Initialize the test values.
    server_impl.resetLastServerValueSeen();
    last_client_callback_value_seen_ = 0;

    // Invoke the Echo method.
    interface_ptr_->EchoInt(7, ValueSaver(&last_client_callback_value_seen_));
    PumpMessages();
  }
  // The binding has now been destroyed and the pipe is closed.

  // Check that server saw the correct value, but the client has not yet.
  EXPECT_EQ(7, server_impl.last_server_value_seen());
  EXPECT_EQ(0, last_client_callback_value_seen_);

  // Now try to run the Callback. This should do nothing since the pipe
  // is closed.
  EXPECT_TRUE(server_impl.RunCallback());
  PumpMessages();

  // Check that the client has still not seen the correct value.
  EXPECT_EQ(0, last_client_callback_value_seen_);

  // Attempt to invoke the method again and confirm that an error was
  // encountered.
  interface_ptr_->EchoInt(13, ValueSaver(&last_client_callback_value_seen_));
  PumpMessages();
  EXPECT_TRUE(interface_ptr_.encountered_error());
}

// Tests that deleting a Callback without running it after the corresponding
// binding has already been deleted does not result in a crash.
TEST_F(BindingCallbackTest, DeleteBindingThenDeleteCallback) {
  // Create the ServerImpl.
  BindingCallbackTestInterfaceImpl server_impl;
  {
    // Create the binding in an inner scope so it can be deleted first.
    Binding<BindingCallbackTestInterface> binding(
        &server_impl,
        MakeRequest<BindingCallbackTestInterface>(handle_server_.Pass()));

    // Initialize the test values.
    server_impl.resetLastServerValueSeen();
    last_client_callback_value_seen_ = 0;

    // Invoke the Echo method.
    interface_ptr_->EchoInt(7, ValueSaver(&last_client_callback_value_seen_));
    PumpMessages();
  }
  // The binding has now been destroyed and the pipe is closed.

  // Check that server saw the correct value, but the client has not yet.
  EXPECT_EQ(7, server_impl.last_server_value_seen());
  EXPECT_EQ(0, last_client_callback_value_seen_);

  // Delete the callback without running it. This should not
  // cause a problem because the insfrastructure can detect that the
  // binding has already been destroyed and the pipe is closed.
  server_impl.DeleteCallback();
}

// Tests that closing a Binding allows us to delete a callback
// without running it without encountering a crash.
TEST_F(BindingCallbackTest, CloseBindingBeforeDeletingCallback) {
  // Create the ServerImpl and the Binding.
  BindingCallbackTestInterfaceImpl server_impl;
  Binding<BindingCallbackTestInterface> binding(
      &server_impl,
      MakeRequest<BindingCallbackTestInterface>(handle_server_.Pass()));

  // Initialize the test values.
  server_impl.resetLastServerValueSeen();
  last_client_callback_value_seen_ = 0;

  // Invoke the Echo method.
  interface_ptr_->EchoInt(7, ValueSaver(&last_client_callback_value_seen_));
  PumpMessages();

  // Check that server saw the correct value, but the client has not yet.
  EXPECT_EQ(7, server_impl.last_server_value_seen());
  EXPECT_EQ(0, last_client_callback_value_seen_);

  // Now close the Binding.
  binding.Close();

  // Delete the callback without running it. This should not
  // cause a crash because the insfrastructure can detect that the
  // binding has already been closed.
  server_impl.DeleteCallback();

  // Check that the client has still not seen the correct value.
  EXPECT_EQ(0, last_client_callback_value_seen_);
}

// Tests that deleting a Callback without using it before the
// Binding has been destroyed or closed results in a DCHECK.
TEST_F(BindingCallbackTest, DeleteCallbackBeforeBindingDeathTest) {
  // Create the ServerImpl and the Binding.
  BindingCallbackTestInterfaceImpl server_impl;
  Binding<BindingCallbackTestInterface> binding(
      &server_impl,
      MakeRequest<BindingCallbackTestInterface>(handle_server_.Pass()));

  // Initialize the test values.
  server_impl.resetLastServerValueSeen();
  last_client_callback_value_seen_ = 0;

  // Invoke the Echo method.
  interface_ptr_->EchoInt(7, ValueSaver(&last_client_callback_value_seen_));
  PumpMessages();

  // Check that server saw the correct value, but the client has not yet.
  EXPECT_EQ(7, server_impl.last_server_value_seen());
  EXPECT_EQ(0, last_client_callback_value_seen_);

#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
  // Delete the callback without running it. This should cause a crash in debug
  // builds due to a DCHECK.
  EXPECT_DEATH(server_impl.DeleteCallback(),
               "Check failed: !callback_was_dropped.");
#endif
}

}  // namespace
}  // namespace test
}  // namespace mojo
<|endoftext|>


<commit_before>#include "joedb/concurrency/Embedded_Connection.h"
#include "joedb/concurrency/Interpreted_Client.h"
#include "joedb/concurrency/Mutex_Lock.h"
#include "joedb/journal/Memory_File.h"

#include "gtest/gtest.h"

using namespace joedb;

/////////////////////////////////////////////////////////////////////////////
TEST(Connection, Interpreted_Client)
/////////////////////////////////////////////////////////////////////////////
{
 Memory_File server_file;
 Embedded_Connection connection(server_file);

 Memory_File client1_file;
 Interpreted_Client client1(connection, client1_file);

 Memory_File client2_file;
 Interpreted_Client client2(connection, client2_file);

 client1.write_transaction
 (
  [](Readable_Writable &db)
  {
   db.create_table("person");
  }
 );

 {
  joedb::Mutex_Lock lock(connection);
 }

 EXPECT_EQ(0, int(client2.get_database().get_tables().size()));
 client2.pull();
 EXPECT_EQ(1, int(client2.get_database().get_tables().size()));

 client2.write_transaction
 (
  [](Readable_Writable &db)
  {
   db.create_table("city");
  }
 );

 EXPECT_EQ(1, int(client1.get_database().get_tables().size()));
 client1.pull();
 EXPECT_EQ(2, int(client1.get_database().get_tables().size()));
}

/////////////////////////////////////////////////////////////////////////////
TEST(Connection, Transaction_Failure)
/////////////////////////////////////////////////////////////////////////////
{
 Memory_File server_file;
 Embedded_Connection connection(server_file);

 Memory_File client1_file;
 Interpreted_Client client1(connection, client1_file);

 Memory_File client2_file;
 Interpreted_Client client2(connection, client2_file);

 client1.write_transaction([](Readable_Writable &db)
 {
  db.create_table("person");
 });

 client2.pull();
 EXPECT_EQ(1, int(client2.get_database().get_tables().size()));

 try
 {
  client1.write_transaction([](Readable_Writable &db)
  {
   db.create_table("city");
   db.checkpoint(Commit_Level::no_commit);
   throw joedb::Exception("cancelled");
  });
  FAIL() << "transaction should have thrown";
 }
 catch (const joedb::Exception &e)
 {
  EXPECT_STREQ(e.what(), "cancelled");
 }

 //
 // A cancelled transaction was not pushed to the server.
 //
 client2.pull();
 EXPECT_EQ(1, int(client2.get_database().get_tables().size()));

 //
 // The cancelled transaction was written locally, which prevents further
 // pulling from the server.
 //

 try
 {
  client1.write_transaction([](Readable_Writable &db)
  {
   db.create_table("country");
  });
  FAIL() << "interrupted write should have prevented transaction";
 }
 catch (const joedb::Exception &e)
 {
  EXPECT_STREQ
  (
   e.what(),
   "Can't pull: failed transaction wrote to local db."
  );
 }

 client2.pull();
 EXPECT_EQ(1, int(client2.get_database().get_tables().size()));
}

/////////////////////////////////////////////////////////////////////////////
TEST(Connection, hash)
/////////////////////////////////////////////////////////////////////////////
{
 Memory_File server_file;
 Embedded_Connection connection(server_file);

 {
  Memory_File client_file;

  {
   Interpreted_Client client(connection, client_file);
   client.write_transaction([](Readable_Writable &db)
   {
    db.create_table("person");
    db.create_table("city");
   });
  }
 }

 {
  Memory_File client_file(Open_Mode::create_new);

  {
   Writable_Journal journal(client_file);
   journal.create_table("country");
   journal.checkpoint(Commit_Level::no_commit);
  }

  try
  {
   client_file.set_position(0);
   client_file.set_mode(Open_Mode::write_existing);
   Interpreted_Client client(connection, client_file);
   FAIL() << "Connection with incompatible file should have failed";
  }
  catch (const joedb::Exception &e)
  {
   EXPECT_STREQ(e.what(), "Hash mismatch");
  }
 }

 {
  Memory_File client_file;

  {
   Writable_Journal client_journal(client_file);
   client_journal.create_table("person");
   client_journal.checkpoint(Commit_Level::no_commit);
  }

  try
  {
   client_file.set_position(0);
   client_file.set_mode(Open_Mode::write_existing);
   Interpreted_Client client(connection, client_file);
   EXPECT_EQ(client.get_database().get_tables().size(), 1ULL);
   client.pull();
   EXPECT_EQ(client.get_database().get_tables().size(), 2ULL);
  }
  catch (const joedb::Exception &e)
  {
   FAIL() << e.what();
  }
 }
}
<commit_msg>remove useless Open_Mode<commit_after>#include "joedb/concurrency/Embedded_Connection.h"
#include "joedb/concurrency/Interpreted_Client.h"
#include "joedb/concurrency/Mutex_Lock.h"
#include "joedb/journal/Memory_File.h"

#include "gtest/gtest.h"

using namespace joedb;

/////////////////////////////////////////////////////////////////////////////
TEST(Connection, Interpreted_Client)
/////////////////////////////////////////////////////////////////////////////
{
 Memory_File server_file;
 Embedded_Connection connection(server_file);

 Memory_File client1_file;
 Interpreted_Client client1(connection, client1_file);

 Memory_File client2_file;
 Interpreted_Client client2(connection, client2_file);

 client1.write_transaction
 (
  [](Readable_Writable &db)
  {
   db.create_table("person");
  }
 );

 {
  joedb::Mutex_Lock lock(connection);
 }

 EXPECT_EQ(0, int(client2.get_database().get_tables().size()));
 client2.pull();
 EXPECT_EQ(1, int(client2.get_database().get_tables().size()));

 client2.write_transaction
 (
  [](Readable_Writable &db)
  {
   db.create_table("city");
  }
 );

 EXPECT_EQ(1, int(client1.get_database().get_tables().size()));
 client1.pull();
 EXPECT_EQ(2, int(client1.get_database().get_tables().size()));
}

/////////////////////////////////////////////////////////////////////////////
TEST(Connection, Transaction_Failure)
/////////////////////////////////////////////////////////////////////////////
{
 Memory_File server_file;
 Embedded_Connection connection(server_file);

 Memory_File client1_file;
 Interpreted_Client client1(connection, client1_file);

 Memory_File client2_file;
 Interpreted_Client client2(connection, client2_file);

 client1.write_transaction([](Readable_Writable &db)
 {
  db.create_table("person");
 });

 client2.pull();
 EXPECT_EQ(1, int(client2.get_database().get_tables().size()));

 try
 {
  client1.write_transaction([](Readable_Writable &db)
  {
   db.create_table("city");
   db.checkpoint(Commit_Level::no_commit);
   throw joedb::Exception("cancelled");
  });
  FAIL() << "transaction should have thrown";
 }
 catch (const joedb::Exception &e)
 {
  EXPECT_STREQ(e.what(), "cancelled");
 }

 //
 // A cancelled transaction was not pushed to the server.
 //
 client2.pull();
 EXPECT_EQ(1, int(client2.get_database().get_tables().size()));

 //
 // The cancelled transaction was written locally, which prevents further
 // pulling from the server.
 //

 try
 {
  client1.write_transaction([](Readable_Writable &db)
  {
   db.create_table("country");
  });
  FAIL() << "interrupted write should have prevented transaction";
 }
 catch (const joedb::Exception &e)
 {
  EXPECT_STREQ
  (
   e.what(),
   "Can't pull: failed transaction wrote to local db."
  );
 }

 client2.pull();
 EXPECT_EQ(1, int(client2.get_database().get_tables().size()));
}

/////////////////////////////////////////////////////////////////////////////
TEST(Connection, hash)
/////////////////////////////////////////////////////////////////////////////
{
 Memory_File server_file;
 Embedded_Connection connection(server_file);

 {
  Memory_File client_file;

  {
   Interpreted_Client client(connection, client_file);
   client.write_transaction([](Readable_Writable &db)
   {
    db.create_table("person");
    db.create_table("city");
   });
  }
 }

 {
  Memory_File client_file;

  {
   Writable_Journal journal(client_file);
   journal.create_table("country");
   journal.checkpoint(Commit_Level::no_commit);
  }

  try
  {
   client_file.set_position(0);
   client_file.set_mode(Open_Mode::write_existing);
   Interpreted_Client client(connection, client_file);
   FAIL() << "Connection with incompatible file should have failed";
  }
  catch (const joedb::Exception &e)
  {
   EXPECT_STREQ(e.what(), "Hash mismatch");
  }
 }

 {
  Memory_File client_file;

  {
   Writable_Journal client_journal(client_file);
   client_journal.create_table("person");
   client_journal.checkpoint(Commit_Level::no_commit);
  }

  try
  {
   client_file.set_position(0);
   client_file.set_mode(Open_Mode::write_existing);
   Interpreted_Client client(connection, client_file);
   EXPECT_EQ(client.get_database().get_tables().size(), 1ULL);
   client.pull();
   EXPECT_EQ(client.get_database().get_tables().size(), 2ULL);
  }
  catch (const joedb::Exception &e)
  {
   FAIL() << e.what();
  }
 }
}
<|endoftext|>


<commit_before>//
// Created by Yihung Lee on 10/31/17.
//

#include "gtest/gtest.h"
#include "LeetCodeHeaders.hpp"

using namespace std;

TEST (Dynamic_Programming, Maximal_Square) {

	vector<vector<char>> matrix(2, std::vector<char>(4, '0'));;
	DynamicQuiz dq;
	EXPECT_EQ (0, dq.maximalSquare(matrix));

}<commit_msg>update<commit_after>//
// Created by Yihung Lee on 10/31/17.
//

#include "gtest/gtest.h"
#include "LeetCodeHeaders.hpp"

using namespace std;

DynamicQuiz dq;

TEST (Dynamic_Programming, Maximal_Square) {

	vector<vector<char>> matrix {{'1', '0', '1','0', '0'},
								 {'1', '0', '1','1', '1'},
								 {'1', '1', '1','1', '1'},
								 {'1', '0', '0','1', '0'}};

	EXPECT_EQ (0, dq.maximalSquare(matrix));
}<|endoftext|>


<commit_before>// -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
// vi: set ts=2 noet:
//
// Copyright (c) 2016 Sergey Lyskov <sergey.lyskov@jhu.edu>
//
// All rights reserved. Use of this source code is governed by a
// MIT license that can be found in the LICENSE file.

/// @file   binder/test/T10.inheritance.hpp
/// @brief  Binder self-test file. Bindings tests for class hierarchy’s.
/// @author Sergey Lyskov

#ifndef _INCLUDED_T10_inheritance_hpp_
#define _INCLUDED_T10_inheritance_hpp_

#include <memory>
#include <string>

class Base
{
protected:
	virtual void foo_protected() {}
	int data;

public:
	void foo() {}

	void maybe() {}

	virtual void f_v() {}
	virtual void f_v_2() {}
};

class Derived : public Base
{
public:
	using Base::foo_protected;
	using Base::data;
};

class Delete : public Base
{
public:
	Delete() = delete;

	void maybe() = delete;
};

class A : public std::enable_shared_from_this
{};

class B : public std::string
{
public:
	B(const B&) = default;
};

class X : public Base
{
public:
	void f_v() final override {}
};

class Y final : public X
{
public:
	void f_v_2() override {}
};

#endif // _INCLUDED_T10_inheritance_hpp_
<commit_msg>fixing const position to match Binder coding style<commit_after>// -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
// vi: set ts=2 noet:
//
// Copyright (c) 2016 Sergey Lyskov <sergey.lyskov@jhu.edu>
//
// All rights reserved. Use of this source code is governed by a
// MIT license that can be found in the LICENSE file.

/// @file   binder/test/T10.inheritance.hpp
/// @brief  Binder self-test file. Bindings tests for class hierarchy’s.
/// @author Sergey Lyskov

#ifndef _INCLUDED_T10_inheritance_hpp_
#define _INCLUDED_T10_inheritance_hpp_

#include <memory>
#include <string>

class Base
{
protected:
	virtual void foo_protected() {}
	int data;

public:
	void foo() {}

	void maybe() {}

	virtual void f_v() {}
	virtual void f_v_2() {}
};

class Derived : public Base
{
public:
	using Base::foo_protected;
	using Base::data;
};

class Delete : public Base
{
public:
	Delete() = delete;

	void maybe() = delete;
};

class A : public std::enable_shared_from_this
{};

class B : public std::string
{
public:
	B(B const &) = default;
};

class X : public Base
{
public:
	void f_v() final override {}
};

class Y final : public X
{
public:
	void f_v_2() override {}
};

#endif // _INCLUDED_T10_inheritance_hpp_
<|endoftext|>


<commit_before>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2011, 2012, 2013, 2014, 2015
Raffaello D. Di Napoli

This file is part of Abaclade.

Abaclade 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.

Abaclade 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 Abaclade. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#include <abaclade.hxx>
#include <abaclade/testing/test_case.hxx>

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace test {

ABC_TESTING_TEST_CASE_FUNC("abc::to_str – int") {
   ABC_TRACE_FUNC(this);

   // Test zero, decimal base.
   ABC_TESTING_ASSERT_EQUAL(to_str(0, istr::empty), ABC_SL("0"));
   ABC_TESTING_ASSERT_EQUAL(to_str(0, ABC_SL(" 1")), ABC_SL(" 0"));
   ABC_TESTING_ASSERT_EQUAL(to_str(0, ABC_SL("01")), ABC_SL("0"));
   ABC_TESTING_ASSERT_EQUAL(to_str(0, ABC_SL(" 2")), ABC_SL(" 0"));
   ABC_TESTING_ASSERT_EQUAL(to_str(0, ABC_SL("02")), ABC_SL("00"));

   // Test positive values, decimal base.
   ABC_TESTING_ASSERT_EQUAL(to_str(1, istr::empty), ABC_SL("1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(1, ABC_SL(" 1")), ABC_SL(" 1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(1, ABC_SL("01")), ABC_SL("1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(1, ABC_SL(" 2")), ABC_SL(" 1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(1, ABC_SL("02")), ABC_SL("01"));

   // Test negative values, decimal base.
   ABC_TESTING_ASSERT_EQUAL(to_str(-1, istr::empty), ABC_SL("-1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(-1, ABC_SL(" 1")), ABC_SL("-1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(-1, ABC_SL("01")), ABC_SL("-1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(-1, ABC_SL(" 2")), ABC_SL("-1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(-1, ABC_SL("02")), ABC_SL("-1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(-1, ABC_SL(" 3")), ABC_SL(" -1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(-1, ABC_SL("03")), ABC_SL("-01"));
}

}} //namespace abc::test

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace test {

ABC_TESTING_TEST_CASE_FUNC("abc::to_str – int8_t") {
   ABC_TRACE_FUNC(this);

   // Test zero, hexadecimal base.
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(0), ABC_SL("x")), ABC_SL("0"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(0), ABC_SL(" 1x")), ABC_SL("0"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(0), ABC_SL("01x")), ABC_SL("0"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(0), ABC_SL(" 2x")), ABC_SL(" 0"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(0), ABC_SL("02x")), ABC_SL("00"));

   // Test positive values, hexadecimal base.
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(1), ABC_SL("x")), ABC_SL("1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(1), ABC_SL(" 1x")), ABC_SL("1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(1), ABC_SL("01x")), ABC_SL("1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(1), ABC_SL(" 2x")), ABC_SL(" 1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(1), ABC_SL("02x")), ABC_SL("01"));

   // Test negative values, hexadecimal base.
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(-1), ABC_SL("x")), ABC_SL("ff"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(-1), ABC_SL(" 1x")), ABC_SL("ff"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(-1), ABC_SL("01x")), ABC_SL("ff"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(-1), ABC_SL(" 2x")), ABC_SL("ff"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(-1), ABC_SL("02x")), ABC_SL("ff"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(-1), ABC_SL(" 3x")), ABC_SL(" ff"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(-1), ABC_SL("03x")), ABC_SL("0ff"));
}

}} //namespace abc::test

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace test {

ABC_TESTING_TEST_CASE_FUNC("abc::to_str – raw pointers") {
   ABC_TRACE_FUNC(this);

   std::uintptr_t iBad = 0xbad;

   // Test nullptr.
   ABC_TESTING_ASSERT_EQUAL(to_str(static_cast<void *>(nullptr), istr::empty), ABC_SL("nullptr"));

   // Test void pointer.
   ABC_TESTING_ASSERT_EQUAL(to_str(reinterpret_cast<void *>(iBad), istr::empty), ABC_SL("0xbad"));

   // Test void const volatile pointer.
   ABC_TESTING_ASSERT_EQUAL(
      to_str(reinterpret_cast<void const volatile *>(iBad), istr::empty), ABC_SL("0xbad")
   );

   // Test function pointer.
   ABC_TESTING_ASSERT_EQUAL(
      to_str(reinterpret_cast<void (*)(int)>(iBad), istr::empty), ABC_SL("0xbad")
   );

   /* Test char_t const pointer. Also confirms that pointers-to-char are NOT treated as strings
   by abc::to_str(). */
   ABC_TESTING_ASSERT_EQUAL(
      to_str(reinterpret_cast<char_t const *>(iBad), istr::empty), ABC_SL("0xbad")
   );
}

}} //namespace abc::test

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace test {

ABC_TESTING_TEST_CASE_FUNC("abc::to_str – smart pointers") {
   ABC_TRACE_FUNC(this);

   int * pi = new int;
   istr sPtr(to_str(pi));

   {
      std::unique_ptr<int> upi(pi);
      // Test non-nullptr std::unique_ptr.
      ABC_TESTING_ASSERT_EQUAL(to_str(upi, istr::empty), sPtr);

      upi.release();
      // Test nullptr std::unique_ptr.
      ABC_TESTING_ASSERT_EQUAL(to_str(upi, istr::empty), ABC_SL("nullptr"));
   }
   {
      std::shared_ptr<int> spi(pi);
      // Test non-nullptr std::shared_ptr.
      ABC_TESTING_ASSERT_EQUAL(to_str(spi, istr::empty), sPtr);
      std::weak_ptr<int> wpi(spi);
      // Test non-nullptr std::weak_ptr.
      ABC_TESTING_ASSERT_EQUAL(to_str(wpi, istr::empty), sPtr);

      spi.reset();
      // Test nullptr std::shared_ptr.
      ABC_TESTING_ASSERT_EQUAL(to_str(spi, istr::empty), ABC_SL("nullptr"));
      // Test expired non-nullptr std::weak_ptr.
      ABC_TESTING_ASSERT_EQUAL(to_str(wpi, istr::empty), ABC_SL("nullptr"));

      wpi.reset();
      // Test nullptr std::weak_ptr.
      ABC_TESTING_ASSERT_EQUAL(to_str(wpi, istr::empty), ABC_SL("nullptr"));
   }
}

}} //namespace abc::test

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace test {

ABC_TESTING_TEST_CASE_FUNC("abc::to_str – STL tuple types") {
   ABC_TRACE_FUNC(this);

#ifdef ABC_CXX_VARIADIC_TEMPLATES
   using std::tuple;
#else
   using abc::_std::tuple;
#endif

   // Test {std,abc::_std}::tuple.
   ABC_TESTING_ASSERT_EQUAL(to_str(tuple<>()), ABC_SL("()"));
   ABC_TESTING_ASSERT_EQUAL(to_str(tuple<int>(1)), ABC_SL("(1)"));
   ABC_TESTING_ASSERT_EQUAL(to_str(tuple<int, int>(1, 2)), ABC_SL("(1, 2)"));
   ABC_TESTING_ASSERT_EQUAL(to_str(tuple<istr, int>(ABC_SL("abc"), 42)), ABC_SL("(abc, 42)"));
}

}} //namespace abc::test

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace test {

ABC_TESTING_TEST_CASE_FUNC("abc::to_str – std::type_info") {
   ABC_TRACE_FUNC(this);

   // Test std::type_info.
   ABC_TESTING_ASSERT_EQUAL(to_str(typeid(1)), ABC_SL("int"));
   ABC_TESTING_ASSERT_EQUAL(to_str(typeid(double)), ABC_SL("double"));
   ABC_TESTING_ASSERT_EQUAL(to_str(typeid(bool)), ABC_SL("bool"));
   ABC_TESTING_ASSERT_EQUAL(to_str(typeid(istr)), ABC_SL("abc::text::istr"));
}

}} //namespace abc::test
<commit_msg>Add more assertion to abc::to_str<std::type_info> test case<commit_after>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2011, 2012, 2013, 2014, 2015
Raffaello D. Di Napoli

This file is part of Abaclade.

Abaclade 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.

Abaclade 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 Abaclade. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#include <abaclade.hxx>
#include <abaclade/testing/test_case.hxx>

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace test {

ABC_TESTING_TEST_CASE_FUNC("abc::to_str – int") {
   ABC_TRACE_FUNC(this);

   // Test zero, decimal base.
   ABC_TESTING_ASSERT_EQUAL(to_str(0, istr::empty), ABC_SL("0"));
   ABC_TESTING_ASSERT_EQUAL(to_str(0, ABC_SL(" 1")), ABC_SL(" 0"));
   ABC_TESTING_ASSERT_EQUAL(to_str(0, ABC_SL("01")), ABC_SL("0"));
   ABC_TESTING_ASSERT_EQUAL(to_str(0, ABC_SL(" 2")), ABC_SL(" 0"));
   ABC_TESTING_ASSERT_EQUAL(to_str(0, ABC_SL("02")), ABC_SL("00"));

   // Test positive values, decimal base.
   ABC_TESTING_ASSERT_EQUAL(to_str(1, istr::empty), ABC_SL("1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(1, ABC_SL(" 1")), ABC_SL(" 1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(1, ABC_SL("01")), ABC_SL("1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(1, ABC_SL(" 2")), ABC_SL(" 1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(1, ABC_SL("02")), ABC_SL("01"));

   // Test negative values, decimal base.
   ABC_TESTING_ASSERT_EQUAL(to_str(-1, istr::empty), ABC_SL("-1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(-1, ABC_SL(" 1")), ABC_SL("-1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(-1, ABC_SL("01")), ABC_SL("-1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(-1, ABC_SL(" 2")), ABC_SL("-1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(-1, ABC_SL("02")), ABC_SL("-1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(-1, ABC_SL(" 3")), ABC_SL(" -1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(-1, ABC_SL("03")), ABC_SL("-01"));
}

}} //namespace abc::test

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace test {

ABC_TESTING_TEST_CASE_FUNC("abc::to_str – int8_t") {
   ABC_TRACE_FUNC(this);

   // Test zero, hexadecimal base.
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(0), ABC_SL("x")), ABC_SL("0"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(0), ABC_SL(" 1x")), ABC_SL("0"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(0), ABC_SL("01x")), ABC_SL("0"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(0), ABC_SL(" 2x")), ABC_SL(" 0"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(0), ABC_SL("02x")), ABC_SL("00"));

   // Test positive values, hexadecimal base.
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(1), ABC_SL("x")), ABC_SL("1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(1), ABC_SL(" 1x")), ABC_SL("1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(1), ABC_SL("01x")), ABC_SL("1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(1), ABC_SL(" 2x")), ABC_SL(" 1"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(1), ABC_SL("02x")), ABC_SL("01"));

   // Test negative values, hexadecimal base.
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(-1), ABC_SL("x")), ABC_SL("ff"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(-1), ABC_SL(" 1x")), ABC_SL("ff"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(-1), ABC_SL("01x")), ABC_SL("ff"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(-1), ABC_SL(" 2x")), ABC_SL("ff"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(-1), ABC_SL("02x")), ABC_SL("ff"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(-1), ABC_SL(" 3x")), ABC_SL(" ff"));
   ABC_TESTING_ASSERT_EQUAL(to_str(std::int8_t(-1), ABC_SL("03x")), ABC_SL("0ff"));
}

}} //namespace abc::test

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace test {

ABC_TESTING_TEST_CASE_FUNC("abc::to_str – raw pointers") {
   ABC_TRACE_FUNC(this);

   std::uintptr_t iBad = 0xbad;

   // Test nullptr.
   ABC_TESTING_ASSERT_EQUAL(to_str(static_cast<void *>(nullptr), istr::empty), ABC_SL("nullptr"));

   // Test void pointer.
   ABC_TESTING_ASSERT_EQUAL(to_str(reinterpret_cast<void *>(iBad), istr::empty), ABC_SL("0xbad"));

   // Test void const volatile pointer.
   ABC_TESTING_ASSERT_EQUAL(
      to_str(reinterpret_cast<void const volatile *>(iBad), istr::empty), ABC_SL("0xbad")
   );

   // Test function pointer.
   ABC_TESTING_ASSERT_EQUAL(
      to_str(reinterpret_cast<void (*)(int)>(iBad), istr::empty), ABC_SL("0xbad")
   );

   /* Test char_t const pointer. Also confirms that pointers-to-char are NOT treated as strings
   by abc::to_str(). */
   ABC_TESTING_ASSERT_EQUAL(
      to_str(reinterpret_cast<char_t const *>(iBad), istr::empty), ABC_SL("0xbad")
   );
}

}} //namespace abc::test

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace test {

ABC_TESTING_TEST_CASE_FUNC("abc::to_str – smart pointers") {
   ABC_TRACE_FUNC(this);

   int * pi = new int;
   istr sPtr(to_str(pi));

   {
      std::unique_ptr<int> upi(pi);
      // Test non-nullptr std::unique_ptr.
      ABC_TESTING_ASSERT_EQUAL(to_str(upi, istr::empty), sPtr);

      upi.release();
      // Test nullptr std::unique_ptr.
      ABC_TESTING_ASSERT_EQUAL(to_str(upi, istr::empty), ABC_SL("nullptr"));
   }
   {
      std::shared_ptr<int> spi(pi);
      // Test non-nullptr std::shared_ptr.
      ABC_TESTING_ASSERT_EQUAL(to_str(spi, istr::empty), sPtr);
      std::weak_ptr<int> wpi(spi);
      // Test non-nullptr std::weak_ptr.
      ABC_TESTING_ASSERT_EQUAL(to_str(wpi, istr::empty), sPtr);

      spi.reset();
      // Test nullptr std::shared_ptr.
      ABC_TESTING_ASSERT_EQUAL(to_str(spi, istr::empty), ABC_SL("nullptr"));
      // Test expired non-nullptr std::weak_ptr.
      ABC_TESTING_ASSERT_EQUAL(to_str(wpi, istr::empty), ABC_SL("nullptr"));

      wpi.reset();
      // Test nullptr std::weak_ptr.
      ABC_TESTING_ASSERT_EQUAL(to_str(wpi, istr::empty), ABC_SL("nullptr"));
   }
}

}} //namespace abc::test

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace test {

ABC_TESTING_TEST_CASE_FUNC("abc::to_str – STL tuple types") {
   ABC_TRACE_FUNC(this);

#ifdef ABC_CXX_VARIADIC_TEMPLATES
   using std::tuple;
#else
   using abc::_std::tuple;
#endif

   // Test {std,abc::_std}::tuple.
   ABC_TESTING_ASSERT_EQUAL(to_str(tuple<>()), ABC_SL("()"));
   ABC_TESTING_ASSERT_EQUAL(to_str(tuple<int>(1)), ABC_SL("(1)"));
   ABC_TESTING_ASSERT_EQUAL(to_str(tuple<int, int>(1, 2)), ABC_SL("(1, 2)"));
   ABC_TESTING_ASSERT_EQUAL(to_str(tuple<istr, int>(ABC_SL("abc"), 42)), ABC_SL("(abc, 42)"));
}

}} //namespace abc::test

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace test {

union union_type {
   int i;
   char ch;
};

struct struct_type {
   int i;
   char ch;
};

class class_type {
   int i;
   char ch;
};

ABC_TESTING_TEST_CASE_FUNC("abc::to_str – std::type_info") {
   ABC_TRACE_FUNC(this);

   // Test std::type_info.
   ABC_TESTING_ASSERT_EQUAL(to_str(typeid(1)), ABC_SL("int"));
   ABC_TESTING_ASSERT_EQUAL(to_str(typeid(double)), ABC_SL("double"));
   ABC_TESTING_ASSERT_EQUAL(to_str(typeid(bool)), ABC_SL("bool"));
   ABC_TESTING_ASSERT_EQUAL(to_str(typeid(union_type )), ABC_SL("abc::test::union_type" ));
   ABC_TESTING_ASSERT_EQUAL(to_str(typeid(struct_type)), ABC_SL("abc::test::struct_type"));
   ABC_TESTING_ASSERT_EQUAL(to_str(typeid(class_type )), ABC_SL("abc::test::class_type" ));
}

}} //namespace abc::test
<|endoftext|>


<commit_before>#include "reply.h"
#include "connection.h"
#include <sstream>
#include <iostream>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

using namespace std;
using http::Reply;
using http::Connection;

Reply::Reply(Connection &cx)
	: Message(cx)
{
	reset();
}

Reply::~Reply()
{
}

void
Reply::set_status(short code, std::string status)
{
	m_code = code;
	m_status = status;
}

void
Reply::prepare()
{
	add_header("Content-Length", m_body.size());

	stringstream ss;
	string crlf("\r\n");
	ss << "HTTP/1.1 " << m_code << " " << m_status << crlf;

	map<string,string>::const_iterator hi;
	for(hi = m_headers.begin(); hi != m_headers.end(); hi++) {
		ss << hi->first << ": " << hi->second << crlf;
	}
	ss << crlf;

	m_data.clear();
	string headers = ss.str();
	m_data.reserve(headers.size() + m_body.size());
	m_data.insert(m_data.end(), headers.begin(), headers.end());

	// insert in-memory part of the body
	m_data.insert(m_data.end(), m_body.buffer_begin(), m_body.buffer_end());
}

void
Reply::reset()
{
	Message::reset();

	m_code = 200;
	m_status = "OK";
	add_header("Connection", "keep-alive");
}

short
Reply::code() const
{
	return m_code;
}

bool
Reply::send()
{
	prepare();

	return send_headers()
		&& m_body.send_from_disk(m_connection);
}

bool
Reply::set_file(const std::string filename)
{
	if (!m_body.set_file(filename)) {
		return false;
	}

	add_header("Content-Length", m_body.size());
	return true;
}

bool
Reply::send_headers()
{
	iterator i;
	for (i = begin(); i != end(); )
	{
		int sent = m_connection.safe_write(&(*i), distance(i, end()));
		if (sent <= 0) {
			// TODO: log
			return false;
		}
		i += sent;
	}
	return true;
}

<commit_msg>Only send content-length if transfer isn't chunked<commit_after>#include "reply.h"
#include "connection.h"
#include <sstream>
#include <iostream>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

using namespace std;
using http::Reply;
using http::Connection;

Reply::Reply(Connection &cx)
	: Message(cx)
{
	reset();
}

Reply::~Reply()
{
}

void
Reply::set_status(short code, std::string status)
{
	m_code = code;
	m_status = status;
}

void
Reply::prepare()
{
	if (get_header("Transfer-Encoding") != "chunked")
		add_header("Content-Length", m_body.size());

	stringstream ss;
	string crlf("\r\n");
	ss << "HTTP/1.1 " << m_code << " " << m_status << crlf;

	map<string,string>::const_iterator hi;
	for(hi = m_headers.begin(); hi != m_headers.end(); hi++) {
		ss << hi->first << ": " << hi->second << crlf;
	}
	ss << crlf;

	m_data.clear();
	string headers = ss.str();
	m_data.reserve(headers.size() + m_body.size());
	m_data.insert(m_data.end(), headers.begin(), headers.end());

	// insert in-memory part of the body
	m_data.insert(m_data.end(), m_body.buffer_begin(), m_body.buffer_end());
}

void
Reply::reset()
{
	Message::reset();

	m_code = 200;
	m_status = "OK";
	add_header("Connection", "keep-alive");
}

short
Reply::code() const
{
	return m_code;
}

bool
Reply::send()
{
	prepare();

	return send_headers()
		&& m_body.send_from_disk(m_connection);
}

bool
Reply::set_file(const std::string filename)
{
	if (!m_body.set_file(filename)) {
		return false;
	}

	add_header("Content-Length", m_body.size());
	return true;
}

bool
Reply::send_headers()
{
	iterator i;
	for (i = begin(); i != end(); )
	{
		int sent = m_connection.safe_write(&(*i), distance(i, end()));
		if (sent <= 0) {
			// TODO: log
			return false;
		}
		i += sent;
	}
	return true;
}

<|endoftext|>


<commit_before>#include "rubymotion.h"
#include "motion-game.h"

#if CC_TARGET_OS_ANDROID
# include "platform/android/jni/JniHelper.h"
#endif

VALUE rb_mMC = Qnil;

#if CC_TARGET_OS_IPHONE || CC_TARGET_OS_APPLETV
#include <unordered_map>
static std::unordered_map<VALUE, std::pair<void*, int>> new_funcs;

static VALUE
singleton_new(VALUE klass, SEL sel, int argc, VALUE *argv)
{
    auto iter = new_funcs.find(klass);
    if (iter == new_funcs.end()) {
	abort();
    }
    auto f = iter->second;
    void *func = f.first;
    int arity = f.second;
    if (arity != -1 && arity != argc) {
	rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
		argc, arity);
    }

    VALUE (*imp)(VALUE, SEL, ...) = (VALUE (*)(VALUE, SEL, ...))func;
    if (arity == -1) {
	return (*imp)(klass, sel, argc, argv);
    }

    switch (argc) {
      case 0:
	return (*imp)(klass, sel);
      case 1:
	return (*imp)(klass, sel, argv[0]);
      case 2:
	return (*imp)(klass, sel, argv[0], argv[1]);
      case 3:
	return (*imp)(klass, sel, argv[0], argv[1], argv[2]);
      case 4:
	return (*imp)(klass, sel, argv[0], argv[1], argv[2], argv[3]);
      case 5:
	return (*imp)(klass, sel, argv[0], argv[1], argv[2], argv[3],
		argv[4]);
      case 6:
	return (*imp)(klass, sel, argv[0], argv[1], argv[2], argv[3],
		argv[4], argv[5]);
      case 7:
	return (*imp)(klass, sel, argv[0], argv[1], argv[2], argv[3],
		argv[4], argv[5], argv[6]);
      case 8:
	return (*imp)(klass, sel, argv[0], argv[1], argv[2], argv[3],
		argv[4], argv[5], argv[6], argv[7]);
      case 9:
	return (*imp)(klass, sel, argv[0], argv[1], argv[2], argv[3],
		argv[4], argv[5], argv[6], argv[7], argv[8]);
      case 10:
	return (*imp)(klass, sel, argv[0], argv[1], argv[2], argv[3],
		argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
      default:
	rb_raise(rb_eArgError, "doesn't support passing more than 10 arguments");
    }
}
#endif

void
rb_define_constructor0(VALUE klass, void *func, int arity)
{
#if CC_TARGET_OS_IPHONE || CC_TARGET_OS_APPLETV
    new_funcs[klass] = std::make_pair(func, arity);
    rb_define_singleton_method(klass, "new", singleton_new, -1);
#else
    rb_define_singleton_method(klass, "new", func, arity);
#endif
}

extern "C"
void
Init_Fluency(void)
{
#if CC_TARGET_OS_ANDROID
    auto java_vm = VM_JAVA_VM();
    assert(java_vm != NULL);
    cocos2d::JniHelper::setJavaVM(java_vm);

#define USE_SYMBOL(x) { extern void *x; void *_sym = x; }
    USE_SYMBOL(Java_org_cocos2dx_lib_GameControllerAdapter_nativeControllerAxisEvent)
    USE_SYMBOL(Java_org_cocos2dx_lib_GameControllerAdapter_nativeControllerButtonEvent)
    USE_SYMBOL(Java_org_cocos2dx_lib_GameControllerAdapter_nativeControllerConnected)
    USE_SYMBOL(Java_org_cocos2dx_lib_GameControllerAdapter_nativeControllerDisconnected)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxVideoHelper_nativeExecuteVideoCallback)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxWebViewHelper_didFailLoading)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxWebViewHelper_didFinishLoading)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxWebViewHelper_onJsCallback)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxWebViewHelper_shouldStartLoading)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxBitmap_nativeInitBitmapDC)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxActivity_getGLContextAttrs)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnSurfaceChanged)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxAccelerometer_onSensorChanged)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxHelper_nativeSetApkPath)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxHelper_nativeSetContext)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxHelper_nativeSetEditTextDialogResult)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeDeleteBackward)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeGetContentText)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInsertText)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnPause)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnResume)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeRender)
    /* USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeKeyDown) */
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesBegin)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesCancel)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesEnd)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesMove)
#undef USE_SYMBOL
#endif

    rb_mMC = rb_define_module("MG");

#if CC_TARGET_OS_ANDROID
# define ADD_FRAME Frame _frame
#else
# define ADD_FRAME
#endif

#define INIT_MODULE(x) \
    extern void Init_##x(void); \
    do { \
	ADD_FRAME; \
	Init_##x(); \
    } \
    while (0);

    INIT_MODULE(Application)
    INIT_MODULE(Director)
    INIT_MODULE(GLView)
    INIT_MODULE(Events)
    INIT_MODULE(Node)
    INIT_MODULE(Layer)
    INIT_MODULE(Menu)
    INIT_MODULE(Sprite)
    INIT_MODULE(Action)
    INIT_MODULE(Particle)
    INIT_MODULE(Audio)
    INIT_MODULE(Types)
    INIT_MODULE(UI)
    INIT_MODULE(FileUtils)

#undef INIT_MODULE
#undef ADD_FRAME
}
<commit_msg>[#67][#50] not check the arity on arm64 architecture in order to avoid crash<commit_after>#include "rubymotion.h"
#include "motion-game.h"

#if CC_TARGET_OS_ANDROID
# include "platform/android/jni/JniHelper.h"
#endif

VALUE rb_mMC = Qnil;

#if CC_TARGET_OS_IPHONE || CC_TARGET_OS_APPLETV
#include <unordered_map>
static std::unordered_map<VALUE, std::pair<void*, int>> new_funcs;

static VALUE
singleton_new(VALUE klass, SEL sel, int argc, VALUE *argv)
{
    auto iter = new_funcs.find(klass);
    if (iter == new_funcs.end()) {
	abort();
    }
    auto f = iter->second;
    void *func = f.first;
    int arity = f.second;
    if (arity != -1 && arity != argc) {
	rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
		argc, arity);
    }

    VALUE (*imp)(VALUE, SEL, ...) = (VALUE (*)(VALUE, SEL, ...))func;
    if (arity == -1) {
	return (*imp)(klass, sel, argc, argv);
    }

    switch (argc) {
      case 0:
	return (*imp)(klass, sel);
      case 1:
	return (*imp)(klass, sel, argv[0]);
      case 2:
	return (*imp)(klass, sel, argv[0], argv[1]);
      case 3:
	return (*imp)(klass, sel, argv[0], argv[1], argv[2]);
      case 4:
	return (*imp)(klass, sel, argv[0], argv[1], argv[2], argv[3]);
      case 5:
	return (*imp)(klass, sel, argv[0], argv[1], argv[2], argv[3],
		argv[4]);
      case 6:
	return (*imp)(klass, sel, argv[0], argv[1], argv[2], argv[3],
		argv[4], argv[5]);
      case 7:
	return (*imp)(klass, sel, argv[0], argv[1], argv[2], argv[3],
		argv[4], argv[5], argv[6]);
      case 8:
	return (*imp)(klass, sel, argv[0], argv[1], argv[2], argv[3],
		argv[4], argv[5], argv[6], argv[7]);
      case 9:
	return (*imp)(klass, sel, argv[0], argv[1], argv[2], argv[3],
		argv[4], argv[5], argv[6], argv[7], argv[8]);
      case 10:
	return (*imp)(klass, sel, argv[0], argv[1], argv[2], argv[3],
		argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
      default:
	rb_raise(rb_eArgError, "doesn't support passing more than 10 arguments");
    }
}
#endif

void
rb_define_constructor0(VALUE klass, void *func, int arity)
{
#if (CC_TARGET_OS_IPHONE || CC_TARGET_OS_APPLETV) && !defined(__arm64__)
    // FIXME : [#67] On arm64 device, it causes an exception.
    new_funcs[klass] = std::make_pair(func, arity);
    rb_define_singleton_method(klass, "new", singleton_new, -1);
#else
    rb_define_singleton_method(klass, "new", func, arity);
#endif
}

extern "C"
void
Init_Fluency(void)
{
#if CC_TARGET_OS_ANDROID
    auto java_vm = VM_JAVA_VM();
    assert(java_vm != NULL);
    cocos2d::JniHelper::setJavaVM(java_vm);

#define USE_SYMBOL(x) { extern void *x; void *_sym = x; }
    USE_SYMBOL(Java_org_cocos2dx_lib_GameControllerAdapter_nativeControllerAxisEvent)
    USE_SYMBOL(Java_org_cocos2dx_lib_GameControllerAdapter_nativeControllerButtonEvent)
    USE_SYMBOL(Java_org_cocos2dx_lib_GameControllerAdapter_nativeControllerConnected)
    USE_SYMBOL(Java_org_cocos2dx_lib_GameControllerAdapter_nativeControllerDisconnected)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxVideoHelper_nativeExecuteVideoCallback)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxWebViewHelper_didFailLoading)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxWebViewHelper_didFinishLoading)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxWebViewHelper_onJsCallback)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxWebViewHelper_shouldStartLoading)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxBitmap_nativeInitBitmapDC)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxActivity_getGLContextAttrs)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnSurfaceChanged)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxAccelerometer_onSensorChanged)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxHelper_nativeSetApkPath)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxHelper_nativeSetContext)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxHelper_nativeSetEditTextDialogResult)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeDeleteBackward)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeGetContentText)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInsertText)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnPause)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnResume)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeRender)
    /* USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeKeyDown) */
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesBegin)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesCancel)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesEnd)
    USE_SYMBOL(Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeTouchesMove)
#undef USE_SYMBOL
#endif

    rb_mMC = rb_define_module("MG");

#if CC_TARGET_OS_ANDROID
# define ADD_FRAME Frame _frame
#else
# define ADD_FRAME
#endif

#define INIT_MODULE(x) \
    extern void Init_##x(void); \
    do { \
	ADD_FRAME; \
	Init_##x(); \
    } \
    while (0);

    INIT_MODULE(Application)
    INIT_MODULE(Director)
    INIT_MODULE(GLView)
    INIT_MODULE(Events)
    INIT_MODULE(Node)
    INIT_MODULE(Layer)
    INIT_MODULE(Menu)
    INIT_MODULE(Sprite)
    INIT_MODULE(Action)
    INIT_MODULE(Particle)
    INIT_MODULE(Audio)
    INIT_MODULE(Types)
    INIT_MODULE(UI)
    INIT_MODULE(FileUtils)

#undef INIT_MODULE
#undef ADD_FRAME
}
<|endoftext|>


<commit_before>//
// Created by david on 2020-05-13.
//
#include "env.h"
#include <math/num.h>
#include <tensors/edges/class_edges_finite.h>
#include <tensors/edges/class_env_ene.h>
#include <tensors/edges/class_env_var.h>
#include <tensors/model/class_model_finite.h>
#include <tensors/state/class_state_finite.h>
#include <tools/common/log.h>

void tools::finite::env::rebuild_edges(const class_state_finite &state, const class_model_finite &model, class_edges_finite &edges) {
    if(not num::all_equal(state.get_length(), model.get_length(), edges.get_length()))
        throw std::runtime_error(
            fmt::format("All lengths not equal: state {} | model {} | edges {}", state.get_length(), model.get_length(), edges.get_length()));
    if(not num::all_equal(state.active_sites, model.active_sites, edges.active_sites))
        throw std::runtime_error(
            fmt::format("All active sites are not equal: state {} | model {} | edges {}", state.active_sites, model.active_sites, edges.active_sites));
    tools::log->trace("Rebuilding edges...");
    tools::common::profile::get_default_prof()["t_env"]->tic();
    size_t min_pos = 0;
    size_t max_pos = state.get_length() - 1;

    // If there are no active sites then we can build up until current position
    size_t posL_active = state.get_position();
    size_t posR_active = state.get_position();
    if(not edges.active_sites.empty()) {
        posL_active = edges.active_sites.front();
        posR_active = edges.active_sites.back();
        edges.eject_inactive_edges(); // Discard edges past the active ones
    }

    auto &ene_front = edges.get_eneL(min_pos);
    auto &var_front = edges.get_varL(min_pos);
    ene_front.set_edge_dims(state.get_mps_site(min_pos), model.get_mpo(min_pos));
    var_front.set_edge_dims(state.get_mps_site(min_pos), model.get_mpo(min_pos));
    std::vector<size_t> ene_pos_log;
    std::vector<size_t> var_pos_log;
    for(size_t pos = min_pos; pos < posL_active; pos++) {
        auto &ene_curr = edges.get_eneL(pos);
        auto &ene_next = edges.get_eneL(pos + 1);
        auto &var_curr = edges.get_varL(pos);
        auto &var_next = edges.get_varL(pos + 1);
        if(not ene_next.has_block()) {
            ene_pos_log.emplace_back(pos + 1);
            ene_next = ene_curr.enlarge(state.get_mps_site(pos), model.get_mpo(pos));
        }
        if(not var_next.has_block()) {
            var_pos_log.emplace_back(pos + 1);
            var_next = var_curr.enlarge(state.get_mps_site(pos), model.get_mpo(pos));
        }
    }
    if(not ene_pos_log.empty()) tools::log->trace("Rebuilt L ene edges: {}", ene_pos_log);
    if(not var_pos_log.empty()) tools::log->trace("Rebuilt L var edges: {}", var_pos_log);

    auto &ene_back = edges.get_eneR(max_pos);
    auto &var_back = edges.get_varR(max_pos);
    ene_back.set_edge_dims(state.get_mps_site(max_pos), model.get_mpo(max_pos));
    var_back.set_edge_dims(state.get_mps_site(max_pos), model.get_mpo(max_pos));
    ene_pos_log.clear();
    var_pos_log.clear();
    for(size_t pos = max_pos; pos > posR_active; pos--) {
        auto &ene_curr = edges.get_eneR(pos);
        auto &ene_prev = edges.get_eneR(pos - 1);
        auto &var_curr = edges.get_varR(pos);
        auto &var_prev = edges.get_varR(pos - 1);
        if(not ene_prev.has_block()) {
            ene_pos_log.emplace_back(pos - 1);
            ene_prev = ene_curr.enlarge(state.get_mps_site(pos), model.get_mpo(pos));
        }
        if(not var_prev.has_block()) {
            var_pos_log.emplace_back(pos - 1);
            var_prev = var_curr.enlarge(state.get_mps_site(pos), model.get_mpo(pos));
        }
    }
    std::reverse(ene_pos_log.begin(), ene_pos_log.end());
    std::reverse(var_pos_log.begin(), var_pos_log.end());
    if(not ene_pos_log.empty()) tools::log->trace("Rebuilt R ene edges: {}", ene_pos_log);
    if(not var_pos_log.empty()) tools::log->trace("Rebuilt R var edges: {}", var_pos_log);
    if(not edges.get_eneL(posL_active).has_block()) throw std::logic_error(fmt::format("Left active ene edge has undefined block"));
    if(not edges.get_varL(posL_active).has_block()) throw std::logic_error(fmt::format("Left active var edge has undefined block"));
    if(not edges.get_eneR(posR_active).has_block()) throw std::logic_error(fmt::format("Right active ene edge has undefined block"));
    if(not edges.get_varR(posR_active).has_block()) throw std::logic_error(fmt::format("Right active var edge has undefined block"));
    tools::common::profile::get_default_prof()["t_env"]->toc();
}
<commit_msg>Added profiling for environment tensor builds<commit_after>//
// Created by david on 2020-05-13.
//
#include "env.h"
#include <math/num.h>
#include <tensors/edges/class_edges_finite.h>
#include <tensors/edges/class_env_ene.h>
#include <tensors/edges/class_env_var.h>
#include <tensors/model/class_model_finite.h>
#include <tensors/state/class_state_finite.h>
#include <tools/common/log.h>
#include <tools/common/prof.h>

void tools::finite::env::rebuild_edges(const class_state_finite &state, const class_model_finite &model, class_edges_finite &edges) {
    if(not num::all_equal(state.get_length(), model.get_length(), edges.get_length()))
        throw std::runtime_error(
            fmt::format("All lengths not equal: state {} | model {} | edges {}", state.get_length(), model.get_length(), edges.get_length()));
    if(not num::all_equal(state.active_sites, model.active_sites, edges.active_sites))
        throw std::runtime_error(
            fmt::format("All active sites are not equal: state {} | model {} | edges {}", state.active_sites, model.active_sites, edges.active_sites));
    tools::log->trace("Rebuilding edges...");
    tools::common::profile::get_default_prof()["t_env"]->tic();
    size_t min_pos = 0;
    size_t max_pos = state.get_length() - 1;

    // If there are no active sites then we can build up until current position
    size_t posL_active = state.get_position();
    size_t posR_active = state.get_position();
    if(not edges.active_sites.empty()) {
        posL_active = edges.active_sites.front();
        posR_active = edges.active_sites.back();
        edges.eject_inactive_edges(); // Discard edges past the active ones
    }

    auto &ene_front = edges.get_eneL(min_pos);
    auto &var_front = edges.get_varL(min_pos);
    ene_front.set_edge_dims(state.get_mps_site(min_pos), model.get_mpo(min_pos));
    var_front.set_edge_dims(state.get_mps_site(min_pos), model.get_mpo(min_pos));
    std::vector<size_t> ene_pos_log;
    std::vector<size_t> var_pos_log;
    for(size_t pos = min_pos; pos < posL_active; pos++) {
        auto &ene_curr = edges.get_eneL(pos);
        auto &ene_next = edges.get_eneL(pos + 1);
        auto &var_curr = edges.get_varL(pos);
        auto &var_next = edges.get_varL(pos + 1);
        if(not ene_next.has_block()) {
            ene_pos_log.emplace_back(pos + 1);
            ene_next = ene_curr.enlarge(state.get_mps_site(pos), model.get_mpo(pos));
        }
        if(not var_next.has_block()) {
            var_pos_log.emplace_back(pos + 1);
            var_next = var_curr.enlarge(state.get_mps_site(pos), model.get_mpo(pos));
        }
    }
    if(not ene_pos_log.empty()) tools::log->trace("Rebuilt L ene edges: {}", ene_pos_log);
    if(not var_pos_log.empty()) tools::log->trace("Rebuilt L var edges: {}", var_pos_log);

    auto &ene_back = edges.get_eneR(max_pos);
    auto &var_back = edges.get_varR(max_pos);
    ene_back.set_edge_dims(state.get_mps_site(max_pos), model.get_mpo(max_pos));
    var_back.set_edge_dims(state.get_mps_site(max_pos), model.get_mpo(max_pos));
    ene_pos_log.clear();
    var_pos_log.clear();
    for(size_t pos = max_pos; pos > posR_active; pos--) {
        auto &ene_curr = edges.get_eneR(pos);
        auto &ene_prev = edges.get_eneR(pos - 1);
        auto &var_curr = edges.get_varR(pos);
        auto &var_prev = edges.get_varR(pos - 1);
        if(not ene_prev.has_block()) {
            ene_pos_log.emplace_back(pos - 1);
            ene_prev = ene_curr.enlarge(state.get_mps_site(pos), model.get_mpo(pos));
        }
        if(not var_prev.has_block()) {
            var_pos_log.emplace_back(pos - 1);
            var_prev = var_curr.enlarge(state.get_mps_site(pos), model.get_mpo(pos));
        }
    }
    std::reverse(ene_pos_log.begin(), ene_pos_log.end());
    std::reverse(var_pos_log.begin(), var_pos_log.end());
    if(not ene_pos_log.empty()) tools::log->trace("Rebuilt R ene edges: {}", ene_pos_log);
    if(not var_pos_log.empty()) tools::log->trace("Rebuilt R var edges: {}", var_pos_log);
    if(not edges.get_eneL(posL_active).has_block()) throw std::logic_error(fmt::format("Left active ene edge has undefined block"));
    if(not edges.get_varL(posL_active).has_block()) throw std::logic_error(fmt::format("Left active var edge has undefined block"));
    if(not edges.get_eneR(posR_active).has_block()) throw std::logic_error(fmt::format("Right active ene edge has undefined block"));
    if(not edges.get_varR(posR_active).has_block()) throw std::logic_error(fmt::format("Right active var edge has undefined block"));
    tools::common::profile::get_default_prof()["t_env"]->toc();
}
<|endoftext|>


<commit_before>// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sky/shell/gpu/mojo/rasterizer_mojo.h"

#include <MGL/mgl_echo.h>

#include "base/trace_event/trace_event.h"
#include "mojo/gpu/gl_texture.h"
#include "mojo/skia/ganesh_texture_surface.h"
#include "sky/shell/shell.h"
#include "third_party/skia/include/core/SkCanvas.h"

namespace sky {
namespace shell {
namespace {

void DidEcho(void* context) {
  TRACE_EVENT_ASYNC_END0("flutter", "DidEcho", context);
  Rasterizer::DrawCallback* callback = static_cast<Rasterizer::DrawCallback*>(context);
  callback->Run();
  delete callback;
}

}  // namespace

const uint32_t kContentImageResourceId = 1;
const uint32_t kRootNodeId = mojo::gfx::composition::kSceneRootNodeId;

std::unique_ptr<Rasterizer> Rasterizer::Create() {
  return std::unique_ptr<Rasterizer>(new RasterizerMojo());
}

RasterizerMojo::RasterizerMojo() : binding_(this), weak_factory_(this) {
}

RasterizerMojo::~RasterizerMojo() {
  weak_factory_.InvalidateWeakPtrs();
  Shell::Shared().PurgeRasterizers();
}

base::WeakPtr<RasterizerMojo> RasterizerMojo::GetWeakPtr() {
  return weak_factory_.GetWeakPtr();
}

base::WeakPtr<Rasterizer> RasterizerMojo::GetWeakRasterizerPtr() {
  return GetWeakPtr();
}

void RasterizerMojo::ConnectToRasterizer (
    mojo::InterfaceRequest<rasterizer::Rasterizer> request ) {
  binding_.Bind(request.Pass());

  Shell::Shared().AddRasterizer(GetWeakRasterizerPtr());
}

void RasterizerMojo::Init(mojo::ApplicationConnectorPtr connector,
                          mojo::gfx::composition::ScenePtr scene) {
  gl_state_.reset(new GLState(connector.get()));
  scene_ = scene.Pass();
}

void RasterizerMojo::Draw(uint64_t layer_tree_ptr,
                          const DrawCallback& callback) {
  TRACE_EVENT0("flutter", "RasterizerMojo::Draw");

  std::unique_ptr<flow::LayerTree> layer_tree(
      reinterpret_cast<flow::LayerTree*>(layer_tree_ptr));

  if (!scene_ || !gl_state_ || gl_state_->gl_context->is_lost()) {
    callback.Run();
    return;
  }

  mojo::Size size;
  size.width = layer_tree->frame_size().width();
  size.height = layer_tree->frame_size().height();

  if (size.width <= 0 || size.height <= 0.0) {
    callback.Run();
    return;
  }

  std::unique_ptr<mojo::GLTexture> texture =
      gl_state_->gl_texture_recycler.GetTexture(size);
  DCHECK(texture);

  {
    mojo::skia::GaneshContext::Scope scope(gl_state_->ganesh_context);
    mojo::skia::GaneshTextureSurface texture_surface(scope, std::move(texture));

    SkCanvas* canvas = texture_surface.canvas();
    flow::PaintContext::ScopedFrame frame =
        paint_context_.AcquireFrame(scope.gr_context().get(), *canvas);
    canvas->clear(SK_ColorBLACK);
    layer_tree->Raster(frame);

    texture = texture_surface.TakeTexture();
  }

  mojo::gfx::composition::ResourcePtr resource =
      gl_state_->gl_texture_recycler.BindTextureResource(std::move(texture));
  DCHECK(resource);

  auto update = mojo::gfx::composition::SceneUpdate::New();
  update->clear_resources = true;
  update->clear_nodes = true;
  update->resources.insert(kContentImageResourceId, resource.Pass());

  auto root_node = mojo::gfx::composition::Node::New();
  root_node->op = mojo::gfx::composition::NodeOp::New();
  root_node->op->set_image(mojo::gfx::composition::ImageNodeOp::New());
  root_node->op->get_image()->content_rect = mojo::RectF::New();
  root_node->op->get_image()->content_rect->width = size.width;
  root_node->op->get_image()->content_rect->height = size.height;
  root_node->op->get_image()->image_resource_id = kContentImageResourceId;
  root_node->hit_test_behavior = mojo::gfx::composition::HitTestBehavior::New();
  root_node->combinator = mojo::gfx::composition::Node::Combinator::MERGE;
  layer_tree->UpdateScene(update.get(), root_node.get());

  update->nodes.insert(kRootNodeId, root_node.Pass());
  scene_->Update(update.Pass());
  auto metadata = mojo::gfx::composition::SceneMetadata::New();
  metadata->version = layer_tree->scene_version();
  scene_->Publish(metadata.Pass());

  last_layer_tree_ = std::move(layer_tree);

  // Ask MGL to ack these commands so that we know we're not getting too far
  // ahead. Ideally Mozart would help us coordinate with the other views.
  DrawCallback* context = new DrawCallback();
  *context = callback;
  TRACE_EVENT_ASYNC_BEGIN0("flutter", "MGLEcho", context);
  MGLEcho(DidEcho, context);
}

flow::LayerTree* RasterizerMojo::GetLastLayerTree() {
  return last_layer_tree_.get();
}

RasterizerMojo::GLState::GLState(mojo::ApplicationConnector* connector)
  : gl_context(mojo::GLContext::CreateOffscreen(connector)),
    gl_texture_recycler(gl_context),
    ganesh_context(new mojo::skia::GaneshContext(gl_context)) {
}

RasterizerMojo::GLState::~GLState() {
}

}  // namespace shell
}  // namespace sky
<commit_msg>Set GLContext before calling MGLEcho.<commit_after>// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sky/shell/gpu/mojo/rasterizer_mojo.h"

#include <MGL/mgl_echo.h>

#include "base/trace_event/trace_event.h"
#include "mojo/gpu/gl_texture.h"
#include "mojo/skia/ganesh_texture_surface.h"
#include "sky/shell/shell.h"
#include "third_party/skia/include/core/SkCanvas.h"

namespace sky {
namespace shell {
namespace {

void DidEcho(void* context) {
  TRACE_EVENT_ASYNC_END0("flutter", "DidEcho", context);
  Rasterizer::DrawCallback* callback = static_cast<Rasterizer::DrawCallback*>(context);
  callback->Run();
  delete callback;
}

}  // namespace

const uint32_t kContentImageResourceId = 1;
const uint32_t kRootNodeId = mojo::gfx::composition::kSceneRootNodeId;

std::unique_ptr<Rasterizer> Rasterizer::Create() {
  return std::unique_ptr<Rasterizer>(new RasterizerMojo());
}

RasterizerMojo::RasterizerMojo() : binding_(this), weak_factory_(this) {
}

RasterizerMojo::~RasterizerMojo() {
  weak_factory_.InvalidateWeakPtrs();
  Shell::Shared().PurgeRasterizers();
}

base::WeakPtr<RasterizerMojo> RasterizerMojo::GetWeakPtr() {
  return weak_factory_.GetWeakPtr();
}

base::WeakPtr<Rasterizer> RasterizerMojo::GetWeakRasterizerPtr() {
  return GetWeakPtr();
}

void RasterizerMojo::ConnectToRasterizer (
    mojo::InterfaceRequest<rasterizer::Rasterizer> request ) {
  binding_.Bind(request.Pass());

  Shell::Shared().AddRasterizer(GetWeakRasterizerPtr());
}

void RasterizerMojo::Init(mojo::ApplicationConnectorPtr connector,
                          mojo::gfx::composition::ScenePtr scene) {
  gl_state_.reset(new GLState(connector.get()));
  scene_ = scene.Pass();
}

void RasterizerMojo::Draw(uint64_t layer_tree_ptr,
                          const DrawCallback& callback) {
  TRACE_EVENT0("flutter", "RasterizerMojo::Draw");

  std::unique_ptr<flow::LayerTree> layer_tree(
      reinterpret_cast<flow::LayerTree*>(layer_tree_ptr));

  if (!scene_ || !gl_state_ || gl_state_->gl_context->is_lost()) {
    callback.Run();
    return;
  }

  mojo::Size size;
  size.width = layer_tree->frame_size().width();
  size.height = layer_tree->frame_size().height();

  if (size.width <= 0 || size.height <= 0.0) {
    callback.Run();
    return;
  }

  std::unique_ptr<mojo::GLTexture> texture =
      gl_state_->gl_texture_recycler.GetTexture(size);
  DCHECK(texture);

  {
    mojo::skia::GaneshContext::Scope scope(gl_state_->ganesh_context);
    mojo::skia::GaneshTextureSurface texture_surface(scope, std::move(texture));

    SkCanvas* canvas = texture_surface.canvas();
    flow::PaintContext::ScopedFrame frame =
        paint_context_.AcquireFrame(scope.gr_context().get(), *canvas);
    canvas->clear(SK_ColorBLACK);
    layer_tree->Raster(frame);

    texture = texture_surface.TakeTexture();
  }

  mojo::gfx::composition::ResourcePtr resource =
      gl_state_->gl_texture_recycler.BindTextureResource(std::move(texture));
  DCHECK(resource);

  auto update = mojo::gfx::composition::SceneUpdate::New();
  update->clear_resources = true;
  update->clear_nodes = true;
  update->resources.insert(kContentImageResourceId, resource.Pass());

  auto root_node = mojo::gfx::composition::Node::New();
  root_node->op = mojo::gfx::composition::NodeOp::New();
  root_node->op->set_image(mojo::gfx::composition::ImageNodeOp::New());
  root_node->op->get_image()->content_rect = mojo::RectF::New();
  root_node->op->get_image()->content_rect->width = size.width;
  root_node->op->get_image()->content_rect->height = size.height;
  root_node->op->get_image()->image_resource_id = kContentImageResourceId;
  root_node->hit_test_behavior = mojo::gfx::composition::HitTestBehavior::New();
  root_node->combinator = mojo::gfx::composition::Node::Combinator::MERGE;
  layer_tree->UpdateScene(update.get(), root_node.get());

  update->nodes.insert(kRootNodeId, root_node.Pass());
  scene_->Update(update.Pass());
  auto metadata = mojo::gfx::composition::SceneMetadata::New();
  metadata->version = layer_tree->scene_version();
  scene_->Publish(metadata.Pass());

  last_layer_tree_ = std::move(layer_tree);

  // Ask MGL to ack these commands so that we know we're not getting too far
  // ahead. Ideally Mozart would help us coordinate with the other views.
  DrawCallback* context = new DrawCallback();
  *context = callback;
  TRACE_EVENT_ASYNC_BEGIN0("flutter", "MGLEcho", context);
  mojo::GLContext::Scope scope(gl_state_->gl_context);
  MGLEcho(DidEcho, context);
}

flow::LayerTree* RasterizerMojo::GetLastLayerTree() {
  return last_layer_tree_.get();
}

RasterizerMojo::GLState::GLState(mojo::ApplicationConnector* connector)
  : gl_context(mojo::GLContext::CreateOffscreen(connector)),
    gl_texture_recycler(gl_context),
    ganesh_context(new mojo::skia::GaneshContext(gl_context)) {
}

RasterizerMojo::GLState::~GLState() {
}

}  // namespace shell
}  // namespace sky
<|endoftext|>