<commit_before>/*-------------------------------------------------------------------------
 * OpenGL Conformance Test Suite
 * -----------------------------
 *
 * Copyright (c) 2016 Google Inc.
 * Copyright (c) 2016 The Khronos Group Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */ /*!
 * \file
 * \brief OpenGL 3.x Test Packages.
 */ /*-------------------------------------------------------------------*/

#include "gl3cTestPackages.hpp"
#include "gl3cClipDistance.hpp"
#include "gl3cCommonBugsTests.hpp"
#include "gl3cCullDistanceTests.hpp"
#include "gl3cGLSLnoperspectiveTests.hpp"
#include "gl3cGPUShader5Tests.hpp"
#include "gl3cTextureSizePromotion.hpp"
#include "gl3cTextureSwizzleTests.hpp"
#include "gl3cTransformFeedbackOverflowQueryTests.hpp"
#include "gl3cTransformFeedbackTests.hpp"
#include "gl4cPipelineStatisticsQueryTests.hpp"
#include "glcPixelStorageModesTests.hpp"
#include "glcFragDepthTests.hpp"
#include "glcInfoTests.hpp"
#include "glcPackedDepthStencilTests.hpp"
#include "glcPackedPixelsTests.hpp"
#include "glcShaderIndexingTests.hpp"
#include "glcShaderIntegerMixTests.hpp"
#include "glcShaderLibrary.hpp"
#include "glcShaderLoopTests.hpp"
#include "glcShaderNegativeTests.hpp"
#include "glcShaderStructTests.hpp"
#include "glcShaderSwitchTests.hpp"
#include "glcTextureRepeatModeTests.hpp"
#include "glcUniformBlockTests.hpp"
#include "glcNearestEdgeTests.hpp"
#include "glcGLSLVectorConstructorTests.hpp"
#include "gluStateReset.hpp"
#include "tcuTestLog.hpp"
#include "tcuWaiverUtil.hpp"

#include "../glesext/texture_shadow_lod/esextcTextureShadowLodFunctionsTest.hpp"

namespace gl3cts
{

TestCaseWrapper::TestCaseWrapper(deqp::TestPackage& package, de::SharedPtr<tcu::WaiverUtil> waiverMechanism)
	: m_testPackage			(package)
	, m_waiverMechanism		(waiverMechanism)
{
}

TestCaseWrapper::~TestCaseWrapper(void)
{
}

void TestCaseWrapper::init(tcu::TestCase* testCase, const std::string& path)
{
	if (m_waiverMechanism->isOnWaiverList(path))
		throw tcu::TestException("Waived test", QP_TEST_RESULT_WAIVER);

	testCase->init();
}

void TestCaseWrapper::deinit(tcu::TestCase* testCase)
{
	testCase->deinit();

	deqp::Context& context = m_testPackage.getContext();
	glu::resetState(context.getRenderContext(), context.getContextInfo());
}

tcu::TestNode::IterateResult TestCaseWrapper::iterate(tcu::TestCase* testCase)
{
	tcu::TestContext&   testCtx   = m_testPackage.getTestContext();
	glu::RenderContext& renderCtx = m_testPackage.getContext().getRenderContext();

	// Clear to black
	{
		const glw::Functions& gl = renderCtx.getFunctions();
		gl.clearColor(0.0, 0.0f, 0.0f, 1.0f);
		gl.clear(GL_COLOR_BUFFER_BIT);
	}

	const tcu::TestCase::IterateResult result = testCase->iterate();

	// Call implementation specific post-iterate routine (usually handles native events and swaps buffers)
	try
	{
		deqp::Context& context = m_testPackage.getContext();
		context.getRenderContext().postIterate();
		return result;
	}
	catch (const tcu::ResourceError&)
	{
		throw tcu::ResourceError(std::string("Resource error in context post-iteration routine"));
		testCtx.setTerminateAfter(true);
		return tcu::TestNode::STOP;
	}
	catch (const std::exception&)
	{
		testCtx.getLog().endCase(QP_TEST_RESULT_FAIL, "Error in context post-iteration routine");
		return tcu::TestNode::STOP;
	}
}

// GL30TestPackage

class GL30ShaderTests : public glcts::TestCaseGroup
{
public:
	GL30ShaderTests(deqp::Context& context) : TestCaseGroup(context, "shaders30", "Shading Language Tests")
	{
	}

	void init(void)
	{
		addChild(new deqp::ShaderLibraryGroup(m_context, "declarations", "Declaration Tests", "gl30/declarations.test"));
		addChild(new deqp::GLSLVectorConstructorTests(m_context, glu::GLSL_VERSION_330));
	}
};

GL30TestPackage::GL30TestPackage(tcu::TestContext& testCtx, const char* packageName, const char* description,
								 glu::ContextType renderContextType)
	: TestPackage(testCtx, packageName, packageName, renderContextType, "gl_cts/data/")
{
	(void)description;
}

GL30TestPackage::~GL30TestPackage(void)
{
}

void GL30TestPackage::init(void)
{
	// Call init() in parent - this creates context.
	TestPackage::init();

	try
	{
		addChild(new deqp::InfoTests(getContext()));
		addChild(new gl3cts::ClipDistance::Tests(getContext()));
		addChild(new gl3cts::GLSLnoperspectiveTests(getContext()));
		addChild(new gl3cts::TransformFeedback::Tests(getContext()));
		addChild(new glcts::TextureRepeatModeTests(getContext()));
		addChild(new GL30ShaderTests(getContext()));
		addChild(new deqp::Functional::TextureShadowLodTest(getContext()));
	}
	catch (...)
	{
		// Destroy context.
		TestPackage::deinit();
		throw;
	}
}

tcu::TestCaseExecutor* GL30TestPackage::createExecutor(void) const
{
	return new TestCaseWrapper(const_cast<GL30TestPackage&>(*this), m_waiverMechanism);
}

// GL31TestPackage

GL31TestPackage::GL31TestPackage(tcu::TestContext& testCtx, const char* packageName, const char* description,
								 glu::ContextType renderContextType)
	: GL30TestPackage(testCtx, packageName, packageName, renderContextType)
{
	(void)description;
}

GL31TestPackage::~GL31TestPackage(void)
{
}

void GL31TestPackage::init(void)
{
	// Call init() in parent - this creates context.
	GL30TestPackage::init();

	try
	{
		addChild(new gl3cts::CommonBugsTests(getContext()));
		addChild(new gl3cts::TextureSizePromotion::Tests(getContext()));
	}
	catch (...)
	{
		// Destroy context.
		TestPackage::deinit();
		throw;
	}
}

// GL32TestPackage

GL32TestPackage::GL32TestPackage(tcu::TestContext& testCtx, const char* packageName, const char* description,
								 glu::ContextType renderContextType)
	: GL31TestPackage(testCtx, packageName, packageName, renderContextType)
{
	(void)description;
}

GL32TestPackage::~GL32TestPackage(void)
{
}

void GL32TestPackage::init(void)
{
	// Call init() in parent - this creates context.
	GL31TestPackage::init();

	try
	{
		addChild(new gl3cts::GPUShader5Tests(getContext()));
		addChild(new gl3cts::TransformFeedbackOverflowQueryTests(
			getContext(), gl3cts::TransformFeedbackOverflowQueryTests::API_GL_ARB_transform_feedback_overflow_query));
		addChild(new glcts::PackedPixelsTests(getContext()));
		addChild(new glcts::PackedDepthStencilTests(getContext()));
	}
	catch (...)
	{
		// Destroy context.
		TestPackage::deinit();
		throw;
	}
}

// OpenGL 3.3 test groups

class GL33ShaderTests : public glcts::TestCaseGroup
{
public:
	GL33ShaderTests(deqp::Context& context) : TestCaseGroup(context, "shaders", "Shading Language Tests")
	{
	}

	void init(void)
	{
		addChild(new deqp::ShaderLibraryGroup(m_context, "arrays", "Array Tests", "gl33/arrays.test"));
		addChild(
			new deqp::ShaderLibraryGroup(m_context, "declarations", "Declaration Tests", "gl33/declarations.test"));
		addChild(new deqp::FragDepthTests(m_context, glu::GLSL_VERSION_330));
		addChild(new deqp::ShaderIndexingTests(m_context, glu::GLSL_VERSION_330));
		addChild(new deqp::ShaderLoopTests(m_context, glu::GLSL_VERSION_330));
		addChild(
			new deqp::ShaderLibraryGroup(m_context, "preprocessor", "Preprocessor Tests", "gl33/preprocessor.test"));
		addChild(new deqp::ShaderStructTests(m_context, glu::GLSL_VERSION_330));
		addChild(new deqp::ShaderSwitchTests(m_context, glu::GLSL_VERSION_330));
		addChild(new deqp::UniformBlockTests(m_context, glu::GLSL_VERSION_330));
		addChild(new deqp::ShaderIntegerMixTests(m_context, glu::GLSL_VERSION_330));
		addChild(new deqp::ShaderNegativeTests(m_context, glu::GLSL_VERSION_330));
	}
};

// GL33TestPackage

GL33TestPackage::GL33TestPackage(tcu::TestContext& testCtx, const char* packageName, const char* description,
								 glu::ContextType renderContextType)
	: GL32TestPackage(testCtx, packageName, packageName, renderContextType)
{
	(void)description;
}

GL33TestPackage::~GL33TestPackage(void)
{
}

void GL33TestPackage::init(void)
{
	// Call init() in parent - this creates context.
	GL32TestPackage::init();

	try
	{
		addChild(new GL33ShaderTests(getContext()));
		addChild(new glcts::PipelineStatisticsQueryTests(getContext()));
		addChild(new glcts::CullDistance::Tests(getContext()));
		addChild(new gl3cts::TextureSwizzleTests(getContext()));
		addChild(new glcts::NearestEdgeCases(getContext()));
		addChild(new glcts::PixelStorageModesTests(getContext(), glu::GLSL_VERSION_330));
	}
	catch (...)
	{
		// Destroy context.
		TestPackage::deinit();
		throw;
	}
}

} // gl3cts
<commit_msg>Lower vector constructor test shader version<commit_after>/*-------------------------------------------------------------------------
 * OpenGL Conformance Test Suite
 * -----------------------------
 *
 * Copyright (c) 2016 Google Inc.
 * Copyright (c) 2016 The Khronos Group Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */ /*!
 * \file
 * \brief OpenGL 3.x Test Packages.
 */ /*-------------------------------------------------------------------*/

#include "gl3cTestPackages.hpp"
#include "gl3cClipDistance.hpp"
#include "gl3cCommonBugsTests.hpp"
#include "gl3cCullDistanceTests.hpp"
#include "gl3cGLSLnoperspectiveTests.hpp"
#include "gl3cGPUShader5Tests.hpp"
#include "gl3cTextureSizePromotion.hpp"
#include "gl3cTextureSwizzleTests.hpp"
#include "gl3cTransformFeedbackOverflowQueryTests.hpp"
#include "gl3cTransformFeedbackTests.hpp"
#include "gl4cPipelineStatisticsQueryTests.hpp"
#include "glcPixelStorageModesTests.hpp"
#include "glcFragDepthTests.hpp"
#include "glcInfoTests.hpp"
#include "glcPackedDepthStencilTests.hpp"
#include "glcPackedPixelsTests.hpp"
#include "glcShaderIndexingTests.hpp"
#include "glcShaderIntegerMixTests.hpp"
#include "glcShaderLibrary.hpp"
#include "glcShaderLoopTests.hpp"
#include "glcShaderNegativeTests.hpp"
#include "glcShaderStructTests.hpp"
#include "glcShaderSwitchTests.hpp"
#include "glcTextureRepeatModeTests.hpp"
#include "glcUniformBlockTests.hpp"
#include "glcNearestEdgeTests.hpp"
#include "glcGLSLVectorConstructorTests.hpp"
#include "gluStateReset.hpp"
#include "tcuTestLog.hpp"
#include "tcuWaiverUtil.hpp"

#include "../glesext/texture_shadow_lod/esextcTextureShadowLodFunctionsTest.hpp"

namespace gl3cts
{

TestCaseWrapper::TestCaseWrapper(deqp::TestPackage& package, de::SharedPtr<tcu::WaiverUtil> waiverMechanism)
	: m_testPackage			(package)
	, m_waiverMechanism		(waiverMechanism)
{
}

TestCaseWrapper::~TestCaseWrapper(void)
{
}

void TestCaseWrapper::init(tcu::TestCase* testCase, const std::string& path)
{
	if (m_waiverMechanism->isOnWaiverList(path))
		throw tcu::TestException("Waived test", QP_TEST_RESULT_WAIVER);

	testCase->init();
}

void TestCaseWrapper::deinit(tcu::TestCase* testCase)
{
	testCase->deinit();

	deqp::Context& context = m_testPackage.getContext();
	glu::resetState(context.getRenderContext(), context.getContextInfo());
}

tcu::TestNode::IterateResult TestCaseWrapper::iterate(tcu::TestCase* testCase)
{
	tcu::TestContext&   testCtx   = m_testPackage.getTestContext();
	glu::RenderContext& renderCtx = m_testPackage.getContext().getRenderContext();

	// Clear to black
	{
		const glw::Functions& gl = renderCtx.getFunctions();
		gl.clearColor(0.0, 0.0f, 0.0f, 1.0f);
		gl.clear(GL_COLOR_BUFFER_BIT);
	}

	const tcu::TestCase::IterateResult result = testCase->iterate();

	// Call implementation specific post-iterate routine (usually handles native events and swaps buffers)
	try
	{
		deqp::Context& context = m_testPackage.getContext();
		context.getRenderContext().postIterate();
		return result;
	}
	catch (const tcu::ResourceError&)
	{
		throw tcu::ResourceError(std::string("Resource error in context post-iteration routine"));
		testCtx.setTerminateAfter(true);
		return tcu::TestNode::STOP;
	}
	catch (const std::exception&)
	{
		testCtx.getLog().endCase(QP_TEST_RESULT_FAIL, "Error in context post-iteration routine");
		return tcu::TestNode::STOP;
	}
}

// GL30TestPackage

class GL30ShaderTests : public glcts::TestCaseGroup
{
public:
	GL30ShaderTests(deqp::Context& context) : TestCaseGroup(context, "shaders30", "Shading Language Tests")
	{
	}

	void init(void)
	{
		addChild(new deqp::ShaderLibraryGroup(m_context, "declarations", "Declaration Tests", "gl30/declarations.test"));
		addChild(new deqp::GLSLVectorConstructorTests(m_context, glu::GLSL_VERSION_130));
	}
};

GL30TestPackage::GL30TestPackage(tcu::TestContext& testCtx, const char* packageName, const char* description,
								 glu::ContextType renderContextType)
	: TestPackage(testCtx, packageName, packageName, renderContextType, "gl_cts/data/")
{
	(void)description;
}

GL30TestPackage::~GL30TestPackage(void)
{
}

void GL30TestPackage::init(void)
{
	// Call init() in parent - this creates context.
	TestPackage::init();

	try
	{
		addChild(new deqp::InfoTests(getContext()));
		addChild(new gl3cts::ClipDistance::Tests(getContext()));
		addChild(new gl3cts::GLSLnoperspectiveTests(getContext()));
		addChild(new gl3cts::TransformFeedback::Tests(getContext()));
		addChild(new glcts::TextureRepeatModeTests(getContext()));
		addChild(new GL30ShaderTests(getContext()));
		addChild(new deqp::Functional::TextureShadowLodTest(getContext()));
	}
	catch (...)
	{
		// Destroy context.
		TestPackage::deinit();
		throw;
	}
}

tcu::TestCaseExecutor* GL30TestPackage::createExecutor(void) const
{
	return new TestCaseWrapper(const_cast<GL30TestPackage&>(*this), m_waiverMechanism);
}

// GL31TestPackage

GL31TestPackage::GL31TestPackage(tcu::TestContext& testCtx, const char* packageName, const char* description,
								 glu::ContextType renderContextType)
	: GL30TestPackage(testCtx, packageName, packageName, renderContextType)
{
	(void)description;
}

GL31TestPackage::~GL31TestPackage(void)
{
}

void GL31TestPackage::init(void)
{
	// Call init() in parent - this creates context.
	GL30TestPackage::init();

	try
	{
		addChild(new gl3cts::CommonBugsTests(getContext()));
		addChild(new gl3cts::TextureSizePromotion::Tests(getContext()));
	}
	catch (...)
	{
		// Destroy context.
		TestPackage::deinit();
		throw;
	}
}

// GL32TestPackage

GL32TestPackage::GL32TestPackage(tcu::TestContext& testCtx, const char* packageName, const char* description,
								 glu::ContextType renderContextType)
	: GL31TestPackage(testCtx, packageName, packageName, renderContextType)
{
	(void)description;
}

GL32TestPackage::~GL32TestPackage(void)
{
}

void GL32TestPackage::init(void)
{
	// Call init() in parent - this creates context.
	GL31TestPackage::init();

	try
	{
		addChild(new gl3cts::GPUShader5Tests(getContext()));
		addChild(new gl3cts::TransformFeedbackOverflowQueryTests(
			getContext(), gl3cts::TransformFeedbackOverflowQueryTests::API_GL_ARB_transform_feedback_overflow_query));
		addChild(new glcts::PackedPixelsTests(getContext()));
		addChild(new glcts::PackedDepthStencilTests(getContext()));
	}
	catch (...)
	{
		// Destroy context.
		TestPackage::deinit();
		throw;
	}
}

// OpenGL 3.3 test groups

class GL33ShaderTests : public glcts::TestCaseGroup
{
public:
	GL33ShaderTests(deqp::Context& context) : TestCaseGroup(context, "shaders", "Shading Language Tests")
	{
	}

	void init(void)
	{
		addChild(new deqp::ShaderLibraryGroup(m_context, "arrays", "Array Tests", "gl33/arrays.test"));
		addChild(
			new deqp::ShaderLibraryGroup(m_context, "declarations", "Declaration Tests", "gl33/declarations.test"));
		addChild(new deqp::FragDepthTests(m_context, glu::GLSL_VERSION_330));
		addChild(new deqp::ShaderIndexingTests(m_context, glu::GLSL_VERSION_330));
		addChild(new deqp::ShaderLoopTests(m_context, glu::GLSL_VERSION_330));
		addChild(
			new deqp::ShaderLibraryGroup(m_context, "preprocessor", "Preprocessor Tests", "gl33/preprocessor.test"));
		addChild(new deqp::ShaderStructTests(m_context, glu::GLSL_VERSION_330));
		addChild(new deqp::ShaderSwitchTests(m_context, glu::GLSL_VERSION_330));
		addChild(new deqp::UniformBlockTests(m_context, glu::GLSL_VERSION_330));
		addChild(new deqp::ShaderIntegerMixTests(m_context, glu::GLSL_VERSION_330));
		addChild(new deqp::ShaderNegativeTests(m_context, glu::GLSL_VERSION_330));
	}
};

// GL33TestPackage

GL33TestPackage::GL33TestPackage(tcu::TestContext& testCtx, const char* packageName, const char* description,
								 glu::ContextType renderContextType)
	: GL32TestPackage(testCtx, packageName, packageName, renderContextType)
{
	(void)description;
}

GL33TestPackage::~GL33TestPackage(void)
{
}

void GL33TestPackage::init(void)
{
	// Call init() in parent - this creates context.
	GL32TestPackage::init();

	try
	{
		addChild(new GL33ShaderTests(getContext()));
		addChild(new glcts::PipelineStatisticsQueryTests(getContext()));
		addChild(new glcts::CullDistance::Tests(getContext()));
		addChild(new gl3cts::TextureSwizzleTests(getContext()));
		addChild(new glcts::NearestEdgeCases(getContext()));
		addChild(new glcts::PixelStorageModesTests(getContext(), glu::GLSL_VERSION_330));
	}
	catch (...)
	{
		// Destroy context.
		TestPackage::deinit();
		throw;
	}
}

} // gl3cts
<|endoftext|>


<commit_before><commit_msg>lokdocview: couple for missing static_cast<GParamFlags>()<commit_after><|endoftext|>


<commit_before>#include <iostream>
#include <iomanip>
#include <string>
#include <pcrecpp.h>

#include "net/net.h"

extern "C" {
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/if_ether.h>
}

static inline std::string ipv4addressToString(const void * src) {
  char ip[INET_ADDRSTRLEN];
  inet_ntop(AF_INET, src, ip, INET_ADDRSTRLEN);
  return std::string(ip);
}

namespace mckeys {

using namespace std;

// Like getInstance. Used for creating commands from packets.
MemcacheCommand MemcacheCommand::create(const Packet& pkt,
                                        const bpf_u_int32 captureAddress,
                                        const memcache_command_t expectedCmdType)
{
  static ssize_t ether_header_sz = sizeof(struct ether_header);
  static ssize_t ip_sz = sizeof(struct ip);

  const struct ether_header* ethernetHeader;
  const struct ip* ipHeader;
  const struct tcphdr* tcpHeader;

  const Packet::Header* pkthdr = &pkt.getHeader();
  const Packet::Data* packet = pkt.getData();

  u_char *data;
  uint32_t dataLength = 0;
  uint32_t dataOffset;

  string sourceAddress = "";
  string destinationAddress = "";

  // must be an IP packet
  // TODO add support for dumping localhost
  ethernetHeader = (struct ether_header*)packet;
  auto etype = ntohs(ethernetHeader->ether_type);
  if (etype != ETHERTYPE_IP) {
    return MemcacheCommand();
  }

  // must be TCP - TODO add support for UDP
  ipHeader = (struct ip*)(packet + ether_header_sz);
  auto itype = ipHeader->ip_p;
  if (itype != IPPROTO_TCP) {
    return MemcacheCommand();
  }
  sourceAddress = ipv4addressToString(&(ipHeader->ip_src));
  destinationAddress = ipv4addressToString(&(ipHeader->ip_dst));

  tcpHeader = (struct tcphdr*)(packet + ether_header_sz + ip_sz);
  dataOffset = ether_header_sz + ip_sz + (tcpHeader->doff * 4);
  data = (u_char*)(packet + dataOffset);
  dataLength = pkthdr->len - dataOffset;
  if (dataLength > pkthdr->caplen) {
    dataLength = pkthdr->caplen;
  }

  // The packet was destined for our capture address, this is a request
  // This bit of optimization lets us ignore a reasonably large percentage of
  // traffic
  if (expectedCmdType == MC_REQUEST) {
    if (ipHeader->ip_dst.s_addr == captureAddress) { // a request packet to server
      return makeRequestCommand(data, dataLength, sourceAddress, destinationAddress);
    }
  } else if (expectedCmdType == MC_RESPONSE) {
    if (ipHeader->ip_src.s_addr == captureAddress) { // a response packet from server
      return makeResponseCommand(data, dataLength, sourceAddress, destinationAddress);
    }
  }
  return MemcacheCommand();
}

// protected default constructor
MemcacheCommand::MemcacheCommand()
  : cmdType_(MC_UNKNOWN),
    sourceAddress_(),
    destinationAddress_(),
    commandName_(),
    objectKey_(),
    objectSize_(0)
{}

// protected constructor
MemcacheCommand::MemcacheCommand(const memcache_command_t cmdType,
                                 const string sourceAddress,
                                 const string destinationAddress,
                                 const string commandName,
                                 const string objectKey,
                                 uint32_t objectSize)
    : cmdType_(cmdType),
      sourceAddress_(sourceAddress),
      destinationAddress_(destinationAddress),
      commandName_(commandName),
      objectKey_(objectKey),
      objectSize_(objectSize)
{}

// static protected
MemcacheCommand MemcacheCommand::makeRequestCommand(u_char* data,
                                                    int length,
                                                    string sourceAddress,
                                                    string destinationAddress)
{
  // set <key> <flags> <exptime> <bytes> [noreply]\r\n
  static string commandName = "set";
  static pcrecpp::RE re(commandName + string(" (\\S+) \\d+ \\d+ (\\d+)"),
                        pcrecpp::RE_Options(PCRE_MULTILINE));
  string key;
  int size = -1;
  string input = "";

  for (int i = 0; i < length; i++) {
    int cid = (int)data[i];
    if (isprint(cid) || cid == 10 || cid == 13) {
      input += static_cast<char>(data[i]);
    }
  }
  if (input.length() < 11) { // set k 0 0 1
    return MemcacheCommand();
  }

  re.PartialMatch(input, &key, &size);
  if (size >= 0) {
    return MemcacheCommand(MC_REQUEST, sourceAddress, destinationAddress, commandName, key, size);
  }
  return MemcacheCommand();
}

// static protected
MemcacheCommand MemcacheCommand::makeResponseCommand(u_char *data,
                                                     int length,
                                                     string sourceAddress,
                                                     string destinationAddress)
{
  // VALUE <key> <flags> <bytes> [<cas unique>]\r\n
  static string commandName = "get";
  static pcrecpp::RE re("VALUE (\\S+) \\d+ (\\d+)",
                        pcrecpp::RE_Options(PCRE_MULTILINE));
  string key;
  int size = -1;
  string input = "";

  for (int i = 0; i < length; i++) {
    int cid = (int)data[i];
    if (isprint(cid) || cid == 10 || cid == 13) {
      input += static_cast<char>(cid);
    }
  }
  if (input.length() < 11) { // VALUE k 0 1
    return MemcacheCommand();
  }

  re.PartialMatch(input, &key, &size);
  if (size >= 0) {
    return MemcacheCommand(MC_RESPONSE, sourceAddress, destinationAddress, commandName, key, size);
  } else {
    return MemcacheCommand();
  }
}

} // end namespace
<commit_msg>Fix IP header length<commit_after>#include <iostream>
#include <iomanip>
#include <string>
#include <pcrecpp.h>

#include "net/net.h"

extern "C" {
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/if_ether.h>
}

static inline std::string ipv4addressToString(const void * src) {
  char ip[INET_ADDRSTRLEN];
  inet_ntop(AF_INET, src, ip, INET_ADDRSTRLEN);
  return std::string(ip);
}

namespace mckeys {

using namespace std;

// Like getInstance. Used for creating commands from packets.
MemcacheCommand MemcacheCommand::create(const Packet& pkt,
                                        const bpf_u_int32 captureAddress,
                                        const memcache_command_t expectedCmdType)
{
  static ssize_t ethernetHeaderSize = sizeof(struct ether_header);

  const struct ether_header* ethernetHeader;
  const struct ip* ipHeader;
  const struct tcphdr* tcpHeader;

  const Packet::Header* pkthdr = &pkt.getHeader();
  const Packet::Data* packet = pkt.getData();

  u_char *data;
  uint32_t dataLength = 0;
  uint32_t dataOffset;

  string sourceAddress = "";
  string destinationAddress = "";

  // must be an IP packet
  // TODO add support for dumping localhost
  ethernetHeader = (struct ether_header*)packet;
  auto etype = ntohs(ethernetHeader->ether_type);
  if (etype != ETHERTYPE_IP) {
    return MemcacheCommand();
  }

  // must be TCP - TODO add support for UDP
  ipHeader = (struct ip*)(packet + ethernetHeaderSize);
  ssize_t ipHeaderSize = ipHeader->ip_hl * 4;
  auto itype = ipHeader->ip_p;
  if (itype != IPPROTO_TCP) {
    return MemcacheCommand();
  }
  sourceAddress = ipv4addressToString(&(ipHeader->ip_src));
  destinationAddress = ipv4addressToString(&(ipHeader->ip_dst));

  tcpHeader = (struct tcphdr*)(packet + ethernetHeaderSize + ipHeaderSize);
  ssize_t tcpHeaderSize = tcpHeader->doff * 4;
  dataOffset = ethernetHeaderSize + ipHeaderSize + tcpHeaderSize;
  data = (u_char*)(packet + dataOffset);
  dataLength = pkthdr->len - dataOffset;
  if (dataLength > pkthdr->caplen) {
    dataLength = pkthdr->caplen;
  }

  // The packet was destined for our capture address, this is a request
  // This bit of optimization lets us ignore a reasonably large percentage of
  // traffic
  if (expectedCmdType == MC_REQUEST) {
    if (ipHeader->ip_dst.s_addr == captureAddress) { // a request packet to server
      return makeRequestCommand(data, dataLength, sourceAddress, destinationAddress);
    }
  } else if (expectedCmdType == MC_RESPONSE) {
    if (ipHeader->ip_src.s_addr == captureAddress) { // a response packet from server
      return makeResponseCommand(data, dataLength, sourceAddress, destinationAddress);
    }
  }
  return MemcacheCommand();
}

// protected default constructor
MemcacheCommand::MemcacheCommand()
  : cmdType_(MC_UNKNOWN),
    sourceAddress_(),
    destinationAddress_(),
    commandName_(),
    objectKey_(),
    objectSize_(0)
{}

// protected constructor
MemcacheCommand::MemcacheCommand(const memcache_command_t cmdType,
                                 const string sourceAddress,
                                 const string destinationAddress,
                                 const string commandName,
                                 const string objectKey,
                                 uint32_t objectSize)
    : cmdType_(cmdType),
      sourceAddress_(sourceAddress),
      destinationAddress_(destinationAddress),
      commandName_(commandName),
      objectKey_(objectKey),
      objectSize_(objectSize)
{}

// static protected
MemcacheCommand MemcacheCommand::makeRequestCommand(u_char* data,
                                                    int length,
                                                    string sourceAddress,
                                                    string destinationAddress)
{
  // set <key> <flags> <exptime> <bytes> [noreply]\r\n
  static string commandName = "set";
  static pcrecpp::RE re(commandName + string(" (\\S+) \\d+ \\d+ (\\d+)"),
                        pcrecpp::RE_Options(PCRE_MULTILINE));
  string key;
  int size = -1;
  string input = "";

  for (int i = 0; i < length; i++) {
    int cid = (int)data[i];
    if (isprint(cid) || cid == 10 || cid == 13) {
      input += static_cast<char>(data[i]);
    }
  }
  if (input.length() < 11) { // set k 0 0 1
    return MemcacheCommand();
  }

  re.PartialMatch(input, &key, &size);
  if (size >= 0) {
    return MemcacheCommand(MC_REQUEST, sourceAddress, destinationAddress, commandName, key, size);
  }
  return MemcacheCommand();
}

// static protected
MemcacheCommand MemcacheCommand::makeResponseCommand(u_char *data,
                                                     int length,
                                                     string sourceAddress,
                                                     string destinationAddress)
{
  // VALUE <key> <flags> <bytes> [<cas unique>]\r\n
  static string commandName = "get";
  static pcrecpp::RE re("VALUE (\\S+) \\d+ (\\d+)",
                        pcrecpp::RE_Options(PCRE_MULTILINE));
  string key;
  int size = -1;
  string input = "";

  for (int i = 0; i < length; i++) {
    int cid = (int)data[i];
    if (isprint(cid) || cid == 10 || cid == 13) {
      input += static_cast<char>(cid);
    }
  }
  if (input.length() < 11) { // VALUE k 0 1
    return MemcacheCommand();
  }

  re.PartialMatch(input, &key, &size);
  if (size >= 0) {
    return MemcacheCommand(MC_RESPONSE, sourceAddress, destinationAddress, commandName, key, size);
  } else {
    return MemcacheCommand();
  }
}

} // end namespace
<|endoftext|>


<commit_before>#include <memory>
#include <string>

#include "notification_manager.hpp"

namespace gmock_sample
{

notification_manager::notification_manager(std::shared_ptr<notifier> _notifier)
	: notifier_(_notifier)
{
}

bool
notification_manager::has_notifications() const
{
	return this->notification_count_ > 0;
}

void
notification_manager::add(const std::string& notification)
{
	(void)notification;
	++this->notification_count_;
}

std::size_t
notification_manager::notification_count() const
{
	return this->notification_count_;
}

void
notification_manager::notify()
{
	this->notification_count_ = 0;
}

} // gmock_sample.
<commit_msg>Updates notification_manager.notify() to call notifier.exec().<commit_after>#include <memory>
#include <string>

#include "notification_manager.hpp"

namespace gmock_sample
{

notification_manager::notification_manager(std::shared_ptr<notifier> _notifier)
	: notifier_(_notifier)
{
}

bool
notification_manager::has_notifications() const
{
	return this->notification_count_ > 0;
}

void
notification_manager::add(const std::string& notification)
{
	(void)notification;
	++this->notification_count_;
}

std::size_t
notification_manager::notification_count() const
{
	return this->notification_count_;
}

void
notification_manager::notify()
{
	this->notifier_->exec("stub");
	this->notification_count_ = 0;
}

} // gmock_sample.
<|endoftext|>


<commit_before>#ifndef MJOLNIR_READ_SPATIAL_PARTITION
#define MJOLNIR_READ_SPATIAL_PARTITION
#include <mjolnir/core/UnlimitedGridCellList.hpp>
#include <mjolnir/core/PeriodicGridCellList.hpp>
#include <mjolnir/core/NaivePairCalculation.hpp>
#include <mjolnir/core/VerletList.hpp>
#include <mjolnir/util/make_unique.hpp>
#include <mjolnir/util/get_toml_value.hpp>

namespace mjolnir
{

template<typename boundaryT, typename traitsT>
struct celllist_dispatcher;

template<typename realT, typename coordT, typename traitsT>
struct celllist_dispatcher<UnlimitedBoundary<realT, coordT>, traitsT>
{
    typedef UnlimitedGridCellList<traitsT> type;
    typedef realT real_type;

    static UnlimitedGridCellList<traitsT> invoke(const real_type margin)
    {
        return UnlimitedGridCellList<traitsT>(margin);
    }
};

template<typename realT, typename coordT, typename traitsT>
struct celllist_dispatcher<CubicPeriodicBoundary<realT, coordT>, traitsT>
{
    typedef PeriodicGridCellList<traitsT> type;
    typedef realT real_type;

    static PeriodicGridCellList<traitsT> invoke(const real_type margin)
    {
        return PeriodicGridCellList<traitsT>(margin);
    }
};

template<typename traitsT, typename potentialT>
std::unique_ptr<GlobalInteractionBase<traitsT>>
read_spatial_partition_for_distance(const toml::Table& global, potentialT pot)
{
    typedef typename traitsT::real_type real_type;

    const auto& sp = toml_value_at(
            global, "spatial_partition", "[forcefield.global]"
            ).cast<toml::value_t::Table>();
    const auto  type = toml::get<std::string>(
            toml_value_at(sp, "type", "[forcefield.global]"));

    if(type == "CellList")
    {
        using boundary_type = typename traitsT::boundary_type;
        using dispatcher    = celllist_dispatcher<boundary_type, traitsT>;
        using celllist_type = typename dispatcher::type;

        const auto mg = toml::get<real_type>(
                toml_value_at(sp, "margin", "[forcefield.global]"));

        return make_unique<GlobalDistanceInteraction<
            traitsT, potentialT, celllist_type>>(
                std::move(pot), dispatcher::invoke(mg));
    }
    else if(type == "VerletList")
    {
        const auto margin = toml::get<real_type>(toml_value_at(
                    sp, "margin", "[forcefield.global]"));
        return make_unique<GlobalDistanceInteraction<
            traitsT, potentialT, VerletList<traitsT>>>(
                std::move(pot), VerletList<traitsT>(margin));
    }
    else if(type == "Naive")
    {
        return make_unique<GlobalDistanceInteraction<
            traitsT, potentialT, NaivePairCalculation<traitsT>>
                >(std::move(pot), NaivePairCalculation<traitsT>());
    }
    else
    {
        throw std::runtime_error("invalid spatial partition type: " + type);
    }
}

} // mjolnir
#endif// MJOLNIR_READ_SPATIAL_PARTITION
<commit_msg>add logger to read_spatial_partition<commit_after>#ifndef MJOLNIR_READ_SPATIAL_PARTITION
#define MJOLNIR_READ_SPATIAL_PARTITION
#include <mjolnir/core/UnlimitedGridCellList.hpp>
#include <mjolnir/core/PeriodicGridCellList.hpp>
#include <mjolnir/core/NaivePairCalculation.hpp>
#include <mjolnir/core/VerletList.hpp>
#include <mjolnir/util/make_unique.hpp>
#include <mjolnir/util/get_toml_value.hpp>

namespace mjolnir
{

template<typename boundaryT, typename traitsT>
struct celllist_dispatcher;

template<typename realT, typename coordT, typename traitsT>
struct celllist_dispatcher<UnlimitedBoundary<realT, coordT>, traitsT>
{
    typedef UnlimitedGridCellList<traitsT> type;
    typedef realT real_type;

    static UnlimitedGridCellList<traitsT> invoke(const real_type margin)
    {
        return UnlimitedGridCellList<traitsT>(margin);
    }
};

template<typename realT, typename coordT, typename traitsT>
struct celllist_dispatcher<CubicPeriodicBoundary<realT, coordT>, traitsT>
{
    typedef PeriodicGridCellList<traitsT> type;
    typedef realT real_type;

    static PeriodicGridCellList<traitsT> invoke(const real_type margin)
    {
        return PeriodicGridCellList<traitsT>(margin);
    }
};

template<typename traitsT, typename potentialT>
std::unique_ptr<GlobalInteractionBase<traitsT>>
read_spatial_partition_for_distance(const toml::Table& global, potentialT pot)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_SCOPE(read_spatial_partition_for_distance(), 0);
    typedef typename traitsT::real_type real_type;

    const auto& sp = toml_value_at(
            global, "spatial_partition", "[forcefield.global]"
            ).cast<toml::value_t::Table>();
    const auto  type = toml::get<std::string>(
            toml_value_at(sp, "type", "[forcefield.global]"));

    if(type == "CellList")
    {
        MJOLNIR_SCOPE(type == "CellList", 1);
        using boundary_type = typename traitsT::boundary_type;
        using dispatcher    = celllist_dispatcher<boundary_type, traitsT>;
        using celllist_type = typename dispatcher::type;

        const auto mg = toml::get<real_type>(
                toml_value_at(sp, "margin", "[forcefield.global]"));
        MJOLNIR_LOG_INFO("margin = ", mg);

        return make_unique<GlobalDistanceInteraction<
            traitsT, potentialT, celllist_type>>(
                std::move(pot), dispatcher::invoke(mg));
    }
    else if(type == "VerletList")
    {
        MJOLNIR_SCOPE(type == "VerletList", 1);

        const auto margin = toml::get<real_type>(toml_value_at(
                    sp, "margin", "[forcefield.global]"));
        MJOLNIR_LOG_INFO("margin = ", mg);

        return make_unique<GlobalDistanceInteraction<
            traitsT, potentialT, VerletList<traitsT>>>(
                std::move(pot), VerletList<traitsT>(margin));
    }
    else if(type == "Naive")
    {
        MJOLNIR_SCOPE(type == "Naive", 1);
        return make_unique<GlobalDistanceInteraction<
            traitsT, potentialT, NaivePairCalculation<traitsT>>
                >(std::move(pot), NaivePairCalculation<traitsT>());
    }
    else
    {
        throw std::runtime_error("invalid spatial partition type: " + type);
    }
}

} // mjolnir
#endif// MJOLNIR_READ_SPATIAL_PARTITION
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/**
 * @file
 **/

#include "modules/planning/tasks/path_optimizer.h"

#include "modules/planning/common/planning_gflags.h"

namespace apollo {
namespace planning {

using apollo::common::Status;

PathOptimizer::PathOptimizer(const std::string& name) : Task(name) {}

apollo::common::Status PathOptimizer::Execute(
    Frame* frame, ReferenceLineInfo* const reference_line_info) {
  Task::Execute(frame, reference_line_info);
  auto ret = Process(
      reference_line_info->speed_data(), reference_line_info->reference_line(),
      frame->PlanningStartPoint(), reference_line_info->mutable_path_data());
  RecordDebugInfo(reference_line_info->path_data());
  if (ret != Status::OK()) {
    reference_line_info->SetDrivable(false);
    AERROR << "Reference Line " << reference_line_info->Lanes().Id()
           << " is not drivable after " << Name();
  }
  if (reference_line_info->IsChangeLanePath() &&
      reference_line_info->TrajectoryLength() > FLAGS_change_lane_min_length) {
    reference_line_info->SetDrivable(false);
    AERROR << "Change lane reference line is shorter than "
           << FLAGS_change_lane_min_length << ", not drivable";
  }
  return ret;
}

void PathOptimizer::RecordDebugInfo(const PathData& path_data) {
  const auto& path_points = path_data.discretized_path().path_points();
  auto* ptr_optimized_path = reference_line_info_->mutable_debug()
                                 ->mutable_planning_data()
                                 ->add_path();
  ptr_optimized_path->set_name(Name());
  ptr_optimized_path->mutable_path_point()->CopyFrom(
      {path_points.begin(), path_points.end()});
}

}  // namespace planning
}  // namespace apollo
<commit_msg>planning: remove min length requirement for change lane path<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/**
 * @file
 **/

#include "modules/planning/tasks/path_optimizer.h"

#include "modules/planning/common/planning_gflags.h"

namespace apollo {
namespace planning {

using apollo::common::Status;

PathOptimizer::PathOptimizer(const std::string& name) : Task(name) {}

apollo::common::Status PathOptimizer::Execute(
    Frame* frame, ReferenceLineInfo* const reference_line_info) {
  Task::Execute(frame, reference_line_info);
  auto ret = Process(
      reference_line_info->speed_data(), reference_line_info->reference_line(),
      frame->PlanningStartPoint(), reference_line_info->mutable_path_data());
  RecordDebugInfo(reference_line_info->path_data());
  if (ret != Status::OK()) {
    reference_line_info->SetDrivable(false);
    AERROR << "Reference Line " << reference_line_info->Lanes().Id()
           << " is not drivable after " << Name();
  }
  return ret;
}

void PathOptimizer::RecordDebugInfo(const PathData& path_data) {
  const auto& path_points = path_data.discretized_path().path_points();
  auto* ptr_optimized_path = reference_line_info_->mutable_debug()
                                 ->mutable_planning_data()
                                 ->add_path();
  ptr_optimized_path->set_name(Name());
  ptr_optimized_path->mutable_path_point()->CopyFrom(
      {path_points.begin(), path_points.end()});
}

}  // namespace planning
}  // namespace apollo
<|endoftext|>


<commit_before>/****************************************************************************

 This file is part of the GLC-lib library.
 Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
 Version 1.1.0, packaged on March, 2009.

 http://glc-lib.sourceforge.net

 GLC-lib 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 2 of the License, or
 (at your option) any later version.

 GLC-lib 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 GLC-lib; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*****************************************************************************/

//! \file glc_extendedgeomengine.cpp Implementation for the GLC_ExtendedGeomEngine class.

#include "glc_extendedgeomengine.h"
#include "../glc_state.h"

// Default constructor
GLC_ExtendedGeomEngine::GLC_ExtendedGeomEngine()
: GLC_GeomEngine()
, m_Positions()
, m_Normals()
, m_Texels()
, m_NormalVboId(0)
, m_TexelVboId(0)
, m_EngineLodList()
, m_PositionSize(0)
, m_TexelsSize(0)
{
	//m_EngineLodList.append(new GLC_EngineLod());

}

// Copy constructor
GLC_ExtendedGeomEngine::GLC_ExtendedGeomEngine(const GLC_ExtendedGeomEngine& engine)
: GLC_GeomEngine(engine)
, m_Positions(engine.positionVector())
, m_Normals(engine.normalVector())
, m_Texels(engine.texelVector())
, m_NormalVboId(0)
, m_TexelVboId(0)
, m_EngineLodList()
, m_PositionSize(engine.m_PositionSize)
, m_TexelsSize(engine.m_TexelsSize)
{

	const int size= engine.m_EngineLodList.size();
	for (int i= 0; i < size; ++i)
	{
		m_EngineLodList.append(new GLC_EngineLod(*engine.m_EngineLodList.at(i)));
	}

}

GLC_ExtendedGeomEngine::~GLC_ExtendedGeomEngine()
{

	// Delete Normal VBO
	if (0 != m_NormalVboId)
	{
		glDeleteBuffers(1, &m_NormalVboId);
	}

	// Delete Texel VBO
	if (0 != m_TexelVboId)
	{
		glDeleteBuffers(1, &m_TexelVboId);
	}

	const int size= m_EngineLodList.size();
	for (int i= 0; i < size; ++i)
	{
		delete m_EngineLodList.at(i);
	}
}
//////////////////////////////////////////////////////////////////////
// Get Functions
//////////////////////////////////////////////////////////////////////

// Return the Position Vector
GLfloatVector GLC_ExtendedGeomEngine::positionVector() const
{
	if (0 != m_VboId)
	{
		// VBO created get data from VBO
		const int sizeOfVbo= m_PositionSize;
		const GLsizeiptr dataSize= sizeOfVbo * sizeof(float);
		GLfloatVector positionVector(sizeOfVbo);

		glBindBuffer(GL_ARRAY_BUFFER, m_VboId);
		GLvoid* pVbo = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
		memcpy(positionVector.data(), pVbo, dataSize);
		glUnmapBuffer(GL_ARRAY_BUFFER);
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		return positionVector;
	}
	else
	{
		return m_Positions;
	}

}

// Return the normal Vector
GLfloatVector GLC_ExtendedGeomEngine::normalVector() const
{
	if (0 != m_NormalVboId)
	{
		// VBO created get data from VBO
		const int sizeOfVbo= m_PositionSize;
		const GLsizeiptr dataSize= sizeOfVbo * sizeof(float);
		GLfloatVector normalVector(sizeOfVbo);

		glBindBuffer(GL_ARRAY_BUFFER, m_NormalVboId);
		GLvoid* pVbo = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
		memcpy(normalVector.data(), pVbo, dataSize);
		glUnmapBuffer(GL_ARRAY_BUFFER);
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		return normalVector;
	}
	else
	{
		return m_Normals;
	}
}

// Return the texel Vector
GLfloatVector GLC_ExtendedGeomEngine::texelVector() const
{
	if (0 != m_TexelVboId)
	{
		// VBO created get data from VBO
		const int sizeOfVbo= m_TexelsSize;
		const GLsizeiptr dataSize= sizeOfVbo * sizeof(float);
		GLfloatVector texelVector(sizeOfVbo);

		glBindBuffer(GL_ARRAY_BUFFER, m_TexelVboId);
		GLvoid* pVbo = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
		memcpy(texelVector.data(), pVbo, dataSize);
		glUnmapBuffer(GL_ARRAY_BUFFER);
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		return texelVector;
	}
	else
	{
		return m_Texels;
	}
}

//////////////////////////////////////////////////////////////////////
// Set Functions
//////////////////////////////////////////////////////////////////////

// The mesh wich use this engine is finished
void GLC_ExtendedGeomEngine::finished()
{
	m_PositionSize= m_Positions.size();
	m_Positions.clear();
	m_Normals.clear();
	m_TexelsSize= m_Texels.size();
	m_Texels.clear();

	// Finish the LOD
	const int size= m_EngineLodList.size();
	for (int i= 0; i < size; ++i)
	{
		m_EngineLodList[i]->finished();
	}
}
//! If the there is more than 2 LOD Swap the first and last
void GLC_ExtendedGeomEngine::finishedLod()
{
	// Swap the first LOD by the last
	const int size= m_EngineLodList.size();
	if (size > 1)
	{
		GLC_EngineLod* PMasterLod= m_EngineLodList.at(size - 1);
		m_EngineLodList[size - 1]= m_EngineLodList.at(0);
		m_EngineLodList[0]= PMasterLod;
	}
}

// Clear the engine
void GLC_ExtendedGeomEngine::clear()
{
	GLC_GeomEngine::clear();
	m_Positions.clear();
	m_Normals.clear();
	m_Texels.clear();
	m_PositionSize= 0;
	m_TexelsSize= 0;

	// Delete Normal VBO
	if (0 != m_NormalVboId)
	{
		glDeleteBuffers(1, &m_NormalVboId);
		m_NormalVboId= 0;
	}

	// Delete Texel VBO
	if (0 != m_TexelVboId)
	{
		glDeleteBuffers(1, &m_TexelVboId);
		m_TexelVboId= 0;
	}

	const int size= m_EngineLodList.size();
	for (int i= 0; i < size; ++i)
	{
		delete m_EngineLodList.at(i);
	}
	m_EngineLodList.clear();
}

//////////////////////////////////////////////////////////////////////
// OpenGL Functions
//////////////////////////////////////////////////////////////////////
//! Vbo creation
void GLC_ExtendedGeomEngine::createVBOs()
{
	// Create position VBO
	if (0 == m_VboId)
	{
		glGenBuffers(1, &m_VboId);
		glGenBuffers(1, &m_NormalVboId);

		// Create Texel VBO
		if (0 == m_TexelVboId and not m_Texels.isEmpty())
		{
			glGenBuffers(1, &m_TexelVboId);
		}

		const int size= m_EngineLodList.size();
		for (int i= 0; i < size; ++i)
		{
			m_EngineLodList.at(i)->createIBO();
		}
	}
}
//! Ibo Usage
bool GLC_ExtendedGeomEngine::useVBO(bool use, GLC_ExtendedGeomEngine::VboType type)
{
	bool result= true;
	if (use)
	{
		// Chose the right VBO
		if (type == GLC_ExtendedGeomEngine::GLC_Vertex)
		{
			glBindBuffer(GL_ARRAY_BUFFER, m_VboId);
		}
		else if (type == GLC_ExtendedGeomEngine::GLC_Normal)
		{
			glBindBuffer(GL_ARRAY_BUFFER, m_NormalVboId);
		}
		else if ((type == GLC_ExtendedGeomEngine::GLC_Texel) and (0 != m_TexelVboId))
		{
			glBindBuffer(GL_ARRAY_BUFFER, m_TexelVboId);
		}
		else result= false;
	}
	else
	{
		// Unbind VBO
		glBindBuffer(GL_ARRAY_BUFFER, 0);
	}
	return result;

}

<commit_msg>Fix bug in he finishLod method. (LOD ordering).<commit_after>/****************************************************************************

 This file is part of the GLC-lib library.
 Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
 Version 1.1.0, packaged on March, 2009.

 http://glc-lib.sourceforge.net

 GLC-lib 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 2 of the License, or
 (at your option) any later version.

 GLC-lib 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 GLC-lib; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*****************************************************************************/

//! \file glc_extendedgeomengine.cpp Implementation for the GLC_ExtendedGeomEngine class.

#include "glc_extendedgeomengine.h"
#include "../glc_state.h"

// Default constructor
GLC_ExtendedGeomEngine::GLC_ExtendedGeomEngine()
: GLC_GeomEngine()
, m_Positions()
, m_Normals()
, m_Texels()
, m_NormalVboId(0)
, m_TexelVboId(0)
, m_EngineLodList()
, m_PositionSize(0)
, m_TexelsSize(0)
{
	//m_EngineLodList.append(new GLC_EngineLod());

}

// Copy constructor
GLC_ExtendedGeomEngine::GLC_ExtendedGeomEngine(const GLC_ExtendedGeomEngine& engine)
: GLC_GeomEngine(engine)
, m_Positions(engine.positionVector())
, m_Normals(engine.normalVector())
, m_Texels(engine.texelVector())
, m_NormalVboId(0)
, m_TexelVboId(0)
, m_EngineLodList()
, m_PositionSize(engine.m_PositionSize)
, m_TexelsSize(engine.m_TexelsSize)
{

	const int size= engine.m_EngineLodList.size();
	for (int i= 0; i < size; ++i)
	{
		m_EngineLodList.append(new GLC_EngineLod(*engine.m_EngineLodList.at(i)));
	}

}

GLC_ExtendedGeomEngine::~GLC_ExtendedGeomEngine()
{

	// Delete Normal VBO
	if (0 != m_NormalVboId)
	{
		glDeleteBuffers(1, &m_NormalVboId);
	}

	// Delete Texel VBO
	if (0 != m_TexelVboId)
	{
		glDeleteBuffers(1, &m_TexelVboId);
	}

	const int size= m_EngineLodList.size();
	for (int i= 0; i < size; ++i)
	{
		delete m_EngineLodList.at(i);
	}
}
//////////////////////////////////////////////////////////////////////
// Get Functions
//////////////////////////////////////////////////////////////////////

// Return the Position Vector
GLfloatVector GLC_ExtendedGeomEngine::positionVector() const
{
	if (0 != m_VboId)
	{
		// VBO created get data from VBO
		const int sizeOfVbo= m_PositionSize;
		const GLsizeiptr dataSize= sizeOfVbo * sizeof(float);
		GLfloatVector positionVector(sizeOfVbo);

		glBindBuffer(GL_ARRAY_BUFFER, m_VboId);
		GLvoid* pVbo = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
		memcpy(positionVector.data(), pVbo, dataSize);
		glUnmapBuffer(GL_ARRAY_BUFFER);
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		return positionVector;
	}
	else
	{
		return m_Positions;
	}

}

// Return the normal Vector
GLfloatVector GLC_ExtendedGeomEngine::normalVector() const
{
	if (0 != m_NormalVboId)
	{
		// VBO created get data from VBO
		const int sizeOfVbo= m_PositionSize;
		const GLsizeiptr dataSize= sizeOfVbo * sizeof(float);
		GLfloatVector normalVector(sizeOfVbo);

		glBindBuffer(GL_ARRAY_BUFFER, m_NormalVboId);
		GLvoid* pVbo = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
		memcpy(normalVector.data(), pVbo, dataSize);
		glUnmapBuffer(GL_ARRAY_BUFFER);
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		return normalVector;
	}
	else
	{
		return m_Normals;
	}
}

// Return the texel Vector
GLfloatVector GLC_ExtendedGeomEngine::texelVector() const
{
	if (0 != m_TexelVboId)
	{
		// VBO created get data from VBO
		const int sizeOfVbo= m_TexelsSize;
		const GLsizeiptr dataSize= sizeOfVbo * sizeof(float);
		GLfloatVector texelVector(sizeOfVbo);

		glBindBuffer(GL_ARRAY_BUFFER, m_TexelVboId);
		GLvoid* pVbo = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
		memcpy(texelVector.data(), pVbo, dataSize);
		glUnmapBuffer(GL_ARRAY_BUFFER);
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		return texelVector;
	}
	else
	{
		return m_Texels;
	}
}

//////////////////////////////////////////////////////////////////////
// Set Functions
//////////////////////////////////////////////////////////////////////

// The mesh wich use this engine is finished
void GLC_ExtendedGeomEngine::finished()
{
	m_PositionSize= m_Positions.size();
	m_Positions.clear();
	m_Normals.clear();
	m_TexelsSize= m_Texels.size();
	m_Texels.clear();

	// Finish the LOD
	const int size= m_EngineLodList.size();
	for (int i= 0; i < size; ++i)
	{
		m_EngineLodList[i]->finished();
	}
}
// If the there is more than 2 LOD Swap the first and last
void GLC_ExtendedGeomEngine::finishedLod()
{
	// PLace the master LOD at the beginning of the list
	const int size= m_EngineLodList.size();
	if (size > 1)
	{
		GLC_EngineLod* PMasterLod= m_EngineLodList.at(size - 1);
		m_EngineLodList.removeAt(size - 1);
		m_EngineLodList.prepend(PMasterLod);
	}
}

// Clear the engine
void GLC_ExtendedGeomEngine::clear()
{
	GLC_GeomEngine::clear();
	m_Positions.clear();
	m_Normals.clear();
	m_Texels.clear();
	m_PositionSize= 0;
	m_TexelsSize= 0;

	// Delete Normal VBO
	if (0 != m_NormalVboId)
	{
		glDeleteBuffers(1, &m_NormalVboId);
		m_NormalVboId= 0;
	}

	// Delete Texel VBO
	if (0 != m_TexelVboId)
	{
		glDeleteBuffers(1, &m_TexelVboId);
		m_TexelVboId= 0;
	}

	const int size= m_EngineLodList.size();
	for (int i= 0; i < size; ++i)
	{
		delete m_EngineLodList.at(i);
	}
	m_EngineLodList.clear();
}

//////////////////////////////////////////////////////////////////////
// OpenGL Functions
//////////////////////////////////////////////////////////////////////
//! Vbo creation
void GLC_ExtendedGeomEngine::createVBOs()
{
	// Create position VBO
	if (0 == m_VboId)
	{
		glGenBuffers(1, &m_VboId);
		glGenBuffers(1, &m_NormalVboId);

		// Create Texel VBO
		if (0 == m_TexelVboId and not m_Texels.isEmpty())
		{
			glGenBuffers(1, &m_TexelVboId);
		}

		const int size= m_EngineLodList.size();
		for (int i= 0; i < size; ++i)
		{
			m_EngineLodList.at(i)->createIBO();
		}
	}
}
//! Ibo Usage
bool GLC_ExtendedGeomEngine::useVBO(bool use, GLC_ExtendedGeomEngine::VboType type)
{
	bool result= true;
	if (use)
	{
		// Chose the right VBO
		if (type == GLC_ExtendedGeomEngine::GLC_Vertex)
		{
			glBindBuffer(GL_ARRAY_BUFFER, m_VboId);
		}
		else if (type == GLC_ExtendedGeomEngine::GLC_Normal)
		{
			glBindBuffer(GL_ARRAY_BUFFER, m_NormalVboId);
		}
		else if ((type == GLC_ExtendedGeomEngine::GLC_Texel) and (0 != m_TexelVboId))
		{
			glBindBuffer(GL_ARRAY_BUFFER, m_TexelVboId);
		}
		else result= false;
	}
	else
	{
		// Unbind VBO
		glBindBuffer(GL_ARRAY_BUFFER, 0);
	}
	return result;

}

<|endoftext|>


<commit_before>#include "BulletTriangleModel.h"
#include "BtDynamicMesh.h"

namespace sofa
{

namespace component
{

namespace collision
{

template <class DataTypes>
TBulletTriangleModel<DataTypes>::TBulletTriangleModel()
    : TTriangleModel<DataTypes>()
    , margin(initData(&margin, (SReal)0.04, "margin","Margin used for collision detection within bullet"))
    , _bt_mesh(0x0)
    , _bt_gmesh(0x0)
{}

static btRigidBody* localCreateRigidBody(float mass, const btTransform& startTransform,btCollisionShape* shape,float /*processingThreshold*/)
{
    btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE));

    //rigidbody is dynamic if and only if mass is non zero, otherwise static
//    bool isDynamic = (mass != 0.f);

    btVector3 localInertia(0,0,0);
//    if (isDynamic)
//        shape->calculateLocalInertia(mass,localInertia);

    //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects

    btRigidBody* body = new btRigidBody(mass,0,shape,localInertia);

    body->setWorldTransform(startTransform);
 //	body->setContactProcessingThreshold(0.5f);

    return body;
}

template <class DataTypes>
void TBulletTriangleModel<DataTypes>::initBullet(){
    sofa::core::objectmodel::BaseObject::f_listening.setValue(true);
    _bt_mesh = new btTriangleMesh();

    const SeqTriangles & tri = *(this->triangles);//this->_topology->getTriangles();
    const VecCoord & pos = mstate->read(core::ConstVecCoordId::position())->getValue();
    int npoints = mstate->getSize();
    int nTri = _topology->getNbTriangles();

    _bt_mesh->preallocateIndices(nTri * 3);
    _bt_mesh->preallocateVertices(npoints);

    for(int i = 0 ; i < npoints ; ++i){
        btVector3 btP(pos[i][0],pos[i][1],pos[i][2]);
        _bt_mesh->findOrAddVertex(btP,false);
    }

    for(int i = 0 ; i < nTri ; ++i){
        _bt_mesh->addIndex(tri[i][0]);
        _bt_mesh->addIndex(tri[i][1]);
        _bt_mesh->addIndex(tri[i][2]);
    }
    _bt_mesh->getIndexedMeshArray()[0].m_numTriangles = nTri;

    //_bt_gmesh = new btBvhTriangleMeshShape(_bt_mesh,true,true);
    _bt_gmesh = new BtDynamicMesh(_bt_mesh);//new btGImpactMeshShape(_bt_mesh);//
    //_bt_gmesh->setMargin(this->getProximity());
    //double margin = 0.5;//0.5;
    _bt_gmesh->setMargin(margin.getValue());

    btTransform startTransform;
    startTransform.setIdentity();
    startTransform.setOrigin(btVector3(0,0,0));

    _bt_collision_object = localCreateRigidBody(1,startTransform,_bt_gmesh,margin.getValue());///PROCESSING THRESHOLD ??? CONTINUE HERE MORENO !!!!
}

template <class DataTypes>
void TBulletTriangleModel<DataTypes>::init(){
    TTriangleModel<DataTypes>::init();
    initBullet();
}

template <class DataTypes>
void TBulletTriangleModel<DataTypes>::reinit(){
    if(_bt_mesh)
        delete _bt_mesh;
    if(_bt_gmesh)
        delete _bt_gmesh;
    if(_bt_collision_object)
        delete _bt_collision_object;

    init();
}

//template <class MyReal,class ToRead,class ToFill>
//void myFillFunc(const ToRead & pos,int numverts,ToFill vertexbase,int vertexStride){
//    int mystride = vertexStride/sizeof(MyReal);
//    MyReal* castVertexBase = (MyReal*)(vertexbase);
//    for(int i = 0 ; i < numverts ; ++i){
//        castVertexBase[0] = pos[i][0];
//        castVertexBase[1] = pos[i][1];
//        castVertexBase[2] = pos[i][2];

//        castVertexBase += mystride;
//    }
//}

//template <class DataTypes>
//void TBulletTriangleModel<DataTypes>::updateBullet(){
//    //_bt_collision_object->setActivationState(DISABLE_SIMULATION);
//    unsigned char *vertexbase;
//    int numverts;
//    PHY_ScalarType type;
//    int vertexStride;
//    unsigned char *indexbase;
//    int indexstride;
//    int numfaces;
//    PHY_ScalarType indicestype;

//    _bt_mesh->getLockedVertexIndexBase(&vertexbase,numverts,type,vertexStride,&indexbase,indexstride,numfaces,indicestype);

//    const VecCoord & pos = mstate->read(core::ConstVecCoordId::position())->getValue();
//    assert(mstate->getSize() == numverts);

//    if(type == PHY_FLOAT){
//        myFillFunc<float>(pos,numverts,vertexbase,vertexStride);
//    }
//    else if(type == PHY_DOUBLE){
//        myFillFunc<double>(pos,numverts,vertexbase,vertexStride);
//    }
//    else{
//        std::cerr<<"in BulletTriangleModel.inl : not a double nor a float !"<<std::endl;
//        exit(-1);
//    }

//    _bt_gmesh->postUpdate();
//    //_bt_collision_object->setActivationState(ACTIVE_TAG);
//}

template <class DataTypes>
template <class MyReal,class ToRead,class ToFill>
void TBulletTriangleModel<DataTypes>::myFillFunc(const ToRead & pos,int numverts,ToFill vertexbase,int vertexStride){
    int mystride = vertexStride/sizeof(MyReal);
    MyReal* castVertexBase = (MyReal*)(vertexbase);
    for(int i = 0 ; i < numverts ; ++i){
        castVertexBase[0] = pos[i][0];
        castVertexBase[1] = pos[i][1];
        castVertexBase[2] = pos[i][2];

        castVertexBase += mystride;
    }
}

template <class DataTypes>
void TBulletTriangleModel<DataTypes>::updateBullet(){
    //_bt_collision_object->setActivationState(DISABLE_SIMULATION);
    unsigned char *vertexbase;
    int numverts;
    PHY_ScalarType type;
    int vertexStride;
    unsigned char *indexbase;
    int indexstride;
    int numfaces;
    PHY_ScalarType indicestype;

    _bt_mesh->getLockedVertexIndexBase(&vertexbase,numverts,type,vertexStride,&indexbase,indexstride,numfaces,indicestype);

    const VecCoord & pos = mstate->read(core::ConstVecCoordId::position())->getValue();
    assert(mstate->getSize() == numverts);

    if(type == PHY_FLOAT){
        myFillFunc<float>(pos,numverts,vertexbase,vertexStride);
    }
    else if(type == PHY_DOUBLE){
        myFillFunc<double>(pos,numverts,vertexbase,vertexStride);
    }
    else{
        std::cerr<<"in BulletTriangleModel.inl : not a double nor a float !"<<std::endl;
        exit(-1);
    }

    _bt_gmesh->postUpdate();
    //_bt_collision_object->setActivationState(ACTIVE_TAG);
    assert(goodSofaBulletLink());
}

template <class DataTypes>
void TBulletTriangleModel<DataTypes>::handleEvent(sofa::core::objectmodel::Event * ev){
    if(dynamic_cast<sofa::simulation::CollisionBeginEvent*>(ev)){
        updateBullet();
//        _bt_gmesh->updateBound();
//        _bt_gmesh->postUpdate();
    }
}

template <class MyReal,class ToRead,class ToFill>
bool sameVertices(const ToRead & pos,int numverts,ToFill vertexbase,int vertexStride){
    MyReal tol = 1e-5;
    int mystride = vertexStride/sizeof(MyReal);
    MyReal* castVertexBase = (MyReal*)(vertexbase);
    for(int i = 0 ; i < numverts ; ++i){
        for(int j = 0 ; j < 3 ; ++j){
            if(fabs(castVertexBase[j] - pos[i][j]) > tol){
                std::cerr<<"castVertexBase[j] "<<castVertexBase[j]<<" pos[i][j] "<<pos[i][j]<<std::endl;
                return false;
            }
        }

        castVertexBase += mystride;
    }

    return true;
}

template <class DataTypes>
bool TBulletTriangleModel<DataTypes>::goodSofaBulletLink()const{
    const VecCoord & s_X = this->getX();

    const unsigned char *vertexbase;
    int numverts;
    PHY_ScalarType type;
    int vertexStride;
    const unsigned char *indexbase;
    int indexstride;
    int numfaces;
    PHY_ScalarType indicestype;

    _bt_mesh->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts,type,vertexStride,&indexbase,indexstride,numfaces,indicestype);

    assert(indicestype == PHY_INTEGER);

    if(type == PHY_DOUBLE){
        if(!sameVertices<double>(s_X,numverts,vertexbase,vertexStride)){
            return false;
        }
    }
    else{
        if(!sameVertices<float>(s_X,numverts,vertexbase,vertexStride)){
                    return false;
        }
    }

    const int * b_indices = (int*)indexbase;

    const sofa::core::topology::BaseMeshTopology::SeqTriangles & triz = *(this->triangles);

    for(unsigned int i = 0 ; i < triz.size() ; ++i){
        for(int j = 0 ; j < 3 ; ++j){
            if(triz[i][j] != (unsigned int)b_indices[i*3 + j])
                return false;
        }
    }

    return true;
}

//template <class DataTypes>
//void TBulletTriangleModel<DataTypes>::computeBoundingTree(int maxDepth=0){
//    (void)(maxDepth);

//}

}}}
<commit_msg>warning<commit_after>#include "BulletTriangleModel.h"
#include "BtDynamicMesh.h"

namespace sofa
{

namespace component
{

namespace collision
{

template <class DataTypes>
TBulletTriangleModel<DataTypes>::TBulletTriangleModel()
    : TTriangleModel<DataTypes>()
    , margin(initData(&margin, (SReal)0.04, "margin","Margin used for collision detection within bullet"))
    , _bt_mesh(0x0)
    , _bt_gmesh(0x0)
{}

static btRigidBody* localCreateRigidBody(float mass, const btTransform& startTransform,btCollisionShape* shape,float /*processingThreshold*/)
{
    btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE));

    //rigidbody is dynamic if and only if mass is non zero, otherwise static
//    bool isDynamic = (mass != 0.f);

    btVector3 localInertia(0,0,0);
//    if (isDynamic)
//        shape->calculateLocalInertia(mass,localInertia);

    //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects

    btRigidBody* body = new btRigidBody(mass,0,shape,localInertia);

    body->setWorldTransform(startTransform);
 //	body->setContactProcessingThreshold(0.5f);

    return body;
}

template <class DataTypes>
void TBulletTriangleModel<DataTypes>::initBullet(){
    sofa::core::objectmodel::BaseObject::f_listening.setValue(true);
    _bt_mesh = new btTriangleMesh();

    const SeqTriangles & tri = *(this->triangles);//this->_topology->getTriangles();
    const VecCoord & pos = mstate->read(core::ConstVecCoordId::position())->getValue();
    int npoints = mstate->getSize();
    int nTri = _topology->getNbTriangles();

    _bt_mesh->preallocateIndices(nTri * 3);
    _bt_mesh->preallocateVertices(npoints);

    for(int i = 0 ; i < npoints ; ++i){
        btVector3 btP(pos[i][0],pos[i][1],pos[i][2]);
        _bt_mesh->findOrAddVertex(btP,false);
    }

    for(int i = 0 ; i < nTri ; ++i){
        _bt_mesh->addIndex(tri[i][0]);
        _bt_mesh->addIndex(tri[i][1]);
        _bt_mesh->addIndex(tri[i][2]);
    }
    _bt_mesh->getIndexedMeshArray()[0].m_numTriangles = nTri;

    //_bt_gmesh = new btBvhTriangleMeshShape(_bt_mesh,true,true);
    _bt_gmesh = new BtDynamicMesh(_bt_mesh);//new btGImpactMeshShape(_bt_mesh);//
    //_bt_gmesh->setMargin(this->getProximity());
    //double margin = 0.5;//0.5;
    _bt_gmesh->setMargin(margin.getValue());

    btTransform startTransform;
    startTransform.setIdentity();
    startTransform.setOrigin(btVector3(0,0,0));

    _bt_collision_object = localCreateRigidBody(1,startTransform,_bt_gmesh,margin.getValue());///PROCESSING THRESHOLD ??? CONTINUE HERE MORENO !!!!
}

template <class DataTypes>
void TBulletTriangleModel<DataTypes>::init(){
    TTriangleModel<DataTypes>::init();
    initBullet();
}

template <class DataTypes>
void TBulletTriangleModel<DataTypes>::reinit(){
    if(_bt_mesh)
        delete _bt_mesh;
    if(_bt_gmesh)
        delete _bt_gmesh;
    if(_bt_collision_object)
        delete _bt_collision_object;

    init();
}

//template <class MyReal,class ToRead,class ToFill>
//void myFillFunc(const ToRead & pos,int numverts,ToFill vertexbase,int vertexStride){
//    int mystride = vertexStride/sizeof(MyReal);
//    MyReal* castVertexBase = (MyReal*)(vertexbase);
//    for(int i = 0 ; i < numverts ; ++i){
//        castVertexBase[0] = pos[i][0];
//        castVertexBase[1] = pos[i][1];
//        castVertexBase[2] = pos[i][2];

//        castVertexBase += mystride;
//    }
//}

//template <class DataTypes>
//void TBulletTriangleModel<DataTypes>::updateBullet(){
//    //_bt_collision_object->setActivationState(DISABLE_SIMULATION);
//    unsigned char *vertexbase;
//    int numverts;
//    PHY_ScalarType type;
//    int vertexStride;
//    unsigned char *indexbase;
//    int indexstride;
//    int numfaces;
//    PHY_ScalarType indicestype;

//    _bt_mesh->getLockedVertexIndexBase(&vertexbase,numverts,type,vertexStride,&indexbase,indexstride,numfaces,indicestype);

//    const VecCoord & pos = mstate->read(core::ConstVecCoordId::position())->getValue();
//    assert(mstate->getSize() == numverts);

//    if(type == PHY_FLOAT){
//        myFillFunc<float>(pos,numverts,vertexbase,vertexStride);
//    }
//    else if(type == PHY_DOUBLE){
//        myFillFunc<double>(pos,numverts,vertexbase,vertexStride);
//    }
//    else{
//        std::cerr<<"in BulletTriangleModel.inl : not a double nor a float !"<<std::endl;
//        exit(-1);
//    }

//    _bt_gmesh->postUpdate();
//    //_bt_collision_object->setActivationState(ACTIVE_TAG);
//}

template <class DataTypes>
template <class MyReal,class ToRead,class ToFill>
void TBulletTriangleModel<DataTypes>::myFillFunc(const ToRead & pos,int numverts,ToFill vertexbase,int vertexStride){
    int mystride = vertexStride/sizeof(MyReal);
    MyReal* castVertexBase = (MyReal*)(vertexbase);
    for(int i = 0 ; i < numverts ; ++i){
        castVertexBase[0] = pos[i][0];
        castVertexBase[1] = pos[i][1];
        castVertexBase[2] = pos[i][2];

        castVertexBase += mystride;
    }
}

template <class DataTypes>
void TBulletTriangleModel<DataTypes>::updateBullet(){
    //_bt_collision_object->setActivationState(DISABLE_SIMULATION);
    unsigned char *vertexbase;
    int numverts;
    PHY_ScalarType type;
    int vertexStride;
    unsigned char *indexbase;
    int indexstride;
    int numfaces;
    PHY_ScalarType indicestype;

    _bt_mesh->getLockedVertexIndexBase(&vertexbase,numverts,type,vertexStride,&indexbase,indexstride,numfaces,indicestype);

    const VecCoord & pos = mstate->read(core::ConstVecCoordId::position())->getValue();
    assert(mstate->getSize() == (size_t)numverts);

    if(type == PHY_FLOAT){
        myFillFunc<float>(pos,numverts,vertexbase,vertexStride);
    }
    else if(type == PHY_DOUBLE){
        myFillFunc<double>(pos,numverts,vertexbase,vertexStride);
    }
    else{
        std::cerr<<"in BulletTriangleModel.inl : not a double nor a float !"<<std::endl;
        exit(-1);
    }

    _bt_gmesh->postUpdate();
    //_bt_collision_object->setActivationState(ACTIVE_TAG);
    assert(goodSofaBulletLink());
}

template <class DataTypes>
void TBulletTriangleModel<DataTypes>::handleEvent(sofa::core::objectmodel::Event * ev){
    if(dynamic_cast<sofa::simulation::CollisionBeginEvent*>(ev)){
        updateBullet();
//        _bt_gmesh->updateBound();
//        _bt_gmesh->postUpdate();
    }
}

template <class MyReal,class ToRead,class ToFill>
bool sameVertices(const ToRead & pos,int numverts,ToFill vertexbase,int vertexStride){
    MyReal tol = 1e-5;
    int mystride = vertexStride/sizeof(MyReal);
    MyReal* castVertexBase = (MyReal*)(vertexbase);
    for(int i = 0 ; i < numverts ; ++i){
        for(int j = 0 ; j < 3 ; ++j){
            if(fabs(castVertexBase[j] - pos[i][j]) > tol){
                std::cerr<<"castVertexBase[j] "<<castVertexBase[j]<<" pos[i][j] "<<pos[i][j]<<std::endl;
                return false;
            }
        }

        castVertexBase += mystride;
    }

    return true;
}

template <class DataTypes>
bool TBulletTriangleModel<DataTypes>::goodSofaBulletLink()const{
    const VecCoord & s_X = this->getX();

    const unsigned char *vertexbase;
    int numverts;
    PHY_ScalarType type;
    int vertexStride;
    const unsigned char *indexbase;
    int indexstride;
    int numfaces;
    PHY_ScalarType indicestype;

    _bt_mesh->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts,type,vertexStride,&indexbase,indexstride,numfaces,indicestype);

    assert(indicestype == PHY_INTEGER);

    if(type == PHY_DOUBLE){
        if(!sameVertices<double>(s_X,numverts,vertexbase,vertexStride)){
            return false;
        }
    }
    else{
        if(!sameVertices<float>(s_X,numverts,vertexbase,vertexStride)){
                    return false;
        }
    }

    const int * b_indices = (int*)indexbase;

    const sofa::core::topology::BaseMeshTopology::SeqTriangles & triz = *(this->triangles);

    for(unsigned int i = 0 ; i < triz.size() ; ++i){
        for(int j = 0 ; j < 3 ; ++j){
            if(triz[i][j] != (unsigned int)b_indices[i*3 + j])
                return false;
        }
    }

    return true;
}

//template <class DataTypes>
//void TBulletTriangleModel<DataTypes>::computeBoundingTree(int maxDepth=0){
//    (void)(maxDepth);

//}

}}}
<|endoftext|>


<commit_before>// Copyright (c) 2011 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 <string>

#include "base/memory/scoped_ptr.h"
#include "base/utf_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/bookmarks/bookmark_context_menu_controller.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/test/base/testing_profile.h"
#include "content/browser/browser_thread.h"
#include "content/browser/tab_contents/page_navigator.h"
#include "grit/generated_resources.h"
#include "testing/gtest/include/gtest/gtest.h"

#if defined(OS_WIN)
#include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
#endif

// PageNavigator implementation that records the URL.
class TestingPageNavigator : public PageNavigator {
 public:
  // Deprecated. Please use the one-argument variant.
  // TODO(adriansc): Remove this method once refactoring changed all call
  // sites.
  virtual TabContents* OpenURL(const GURL& url,
                               const GURL& referrer,
                               WindowOpenDisposition disposition,
                               content::PageTransition transition) OVERRIDE {
    return OpenURL(OpenURLParams(url, referrer, disposition, transition,
                                 false));
  }

  virtual TabContents* OpenURL(const OpenURLParams& params) OVERRIDE {
    urls_.push_back(params.url);
    return NULL;
  }

  std::vector<GURL> urls_;
};

class BookmarkContextMenuControllerTest : public testing::Test {
 public:
  BookmarkContextMenuControllerTest()
      : ui_thread_(BrowserThread::UI, &message_loop_),
        file_thread_(BrowserThread::FILE, &message_loop_),
        model_(NULL) {
  }

  virtual void SetUp() {
#if defined(OS_WIN)
    BookmarkBarView::testing_ = true;
#endif

    profile_.reset(new TestingProfile());
    profile_->CreateBookmarkModel(true);
    profile_->BlockUntilBookmarkModelLoaded();

    model_ = profile_->GetBookmarkModel();

    AddTestData();
  }

  virtual void TearDown() {
#if defined(OS_WIN)
    BookmarkBarView::testing_ = false;
#endif

    // Flush the message loop to make application verifiers happy.
    message_loop_.RunAllPending();
  }

 protected:
  MessageLoopForUI message_loop_;
  BrowserThread ui_thread_;
  BrowserThread file_thread_;
  scoped_ptr<TestingProfile> profile_;
  BookmarkModel* model_;
  TestingPageNavigator navigator_;

 private:
  // Creates the following structure:
  // a
  // F1
  //  f1a
  //  F11
  //   f11a
  // F2
  // F3
  // F4
  //   f4a
  void AddTestData() {
    const BookmarkNode* bb_node = model_->bookmark_bar_node();
    std::string test_base = "file:///c:/tmp/";
    model_->AddURL(bb_node, 0, ASCIIToUTF16("a"), GURL(test_base + "a"));
    const BookmarkNode* f1 = model_->AddFolder(bb_node, 1, ASCIIToUTF16("F1"));
    model_->AddURL(f1, 0, ASCIIToUTF16("f1a"), GURL(test_base + "f1a"));
    const BookmarkNode* f11 = model_->AddFolder(f1, 1, ASCIIToUTF16("F11"));
    model_->AddURL(f11, 0, ASCIIToUTF16("f11a"), GURL(test_base + "f11a"));
    model_->AddFolder(bb_node, 2, ASCIIToUTF16("F2"));
    model_->AddFolder(bb_node, 3, ASCIIToUTF16("F3"));
    const BookmarkNode* f4 = model_->AddFolder(bb_node, 4, ASCIIToUTF16("F4"));
    model_->AddURL(f4, 0, ASCIIToUTF16("f4a"), GURL(test_base + "f4a"));
  }
};

// Tests Deleting from the menu.
TEST_F(BookmarkContextMenuControllerTest, DeleteURL) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->bookmark_bar_node()->GetChild(0));
  BookmarkContextMenuController controller(
      NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes);
  GURL url = model_->bookmark_bar_node()->GetChild(0)->url();
  ASSERT_TRUE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_REMOVE));
  // Delete the URL.
  controller.ExecuteCommand(IDC_BOOKMARK_BAR_REMOVE);
  // Model shouldn't have URL anymore.
  ASSERT_FALSE(model_->IsBookmarked(url));
}

// Tests open all on a folder with a couple of bookmarks.
TEST_F(BookmarkContextMenuControllerTest, OpenAll) {
  const BookmarkNode* folder = model_->bookmark_bar_node()->GetChild(1);
  bookmark_utils::OpenAll(
      NULL, profile_.get(), &navigator_, folder, NEW_FOREGROUND_TAB);

  // Should have navigated to F1's child, but not F11's child.
  ASSERT_EQ(static_cast<size_t>(1), navigator_.urls_.size());
  ASSERT_TRUE(folder->GetChild(0)->url() == navigator_.urls_[0]);
}

// Tests the enabled state of the menus when supplied an empty vector.
TEST_F(BookmarkContextMenuControllerTest, EmptyNodes) {
  BookmarkContextMenuController controller(
      NULL, NULL, profile_.get(), NULL, model_->other_node(),
      std::vector<const BookmarkNode*>());
  EXPECT_FALSE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_FALSE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_REMOVE));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of the menus when supplied a vector with a single
// url.
TEST_F(BookmarkContextMenuControllerTest, SingleURL) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->bookmark_bar_node()->GetChild(0));
  BookmarkContextMenuController controller(
      NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes);
  EXPECT_TRUE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_TRUE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_REMOVE));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of the menus when supplied a vector with multiple
// urls.
TEST_F(BookmarkContextMenuControllerTest, MultipleURLs) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->bookmark_bar_node()->GetChild(0));
  nodes.push_back(model_->bookmark_bar_node()->GetChild(1)->GetChild(0));
  BookmarkContextMenuController controller(
      NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes);
  EXPECT_TRUE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_TRUE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_REMOVE));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of the menus when supplied an vector with a single
// folder.
TEST_F(BookmarkContextMenuControllerTest, SingleFolder) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->bookmark_bar_node()->GetChild(2));
  BookmarkContextMenuController controller(
      NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes);
  EXPECT_FALSE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_TRUE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_REMOVE));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of the menus when supplied a vector with multiple
// folders, all of which are empty.
TEST_F(BookmarkContextMenuControllerTest, MultipleEmptyFolders) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->bookmark_bar_node()->GetChild(2));
  nodes.push_back(model_->bookmark_bar_node()->GetChild(3));
  BookmarkContextMenuController controller(
      NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes);
  EXPECT_FALSE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_TRUE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_REMOVE));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of the menus when supplied a vector with multiple
// folders, some of which contain URLs.
TEST_F(BookmarkContextMenuControllerTest, MultipleFoldersWithURLs) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->bookmark_bar_node()->GetChild(3));
  nodes.push_back(model_->bookmark_bar_node()->GetChild(4));
  BookmarkContextMenuController controller(
      NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes);
  EXPECT_TRUE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_TRUE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_REMOVE));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of open incognito.
TEST_F(BookmarkContextMenuControllerTest, DisableIncognito) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->bookmark_bar_node()->GetChild(0));
  BookmarkContextMenuController controller(
      NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes);
  profile_->set_incognito(true);
  EXPECT_FALSE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_INCOGNITO));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
}

// Tests that you can't remove/edit when showing the other node.
TEST_F(BookmarkContextMenuControllerTest, DisabledItemsWithOtherNode) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->other_node());
  BookmarkContextMenuController controller(
      NULL, NULL, profile_.get(), NULL, nodes[0], nodes);
  EXPECT_FALSE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_EDIT));
  EXPECT_FALSE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_REMOVE));
}

// Tests the enabled state of the menus when supplied an empty vector and null
// parent.
TEST_F(BookmarkContextMenuControllerTest, EmptyNodesNullParent) {
  BookmarkContextMenuController controller(
      NULL, NULL, profile_.get(), NULL, NULL,
      std::vector<const BookmarkNode*>());
  EXPECT_FALSE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_FALSE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_REMOVE));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_NEW_FOLDER));
}

// Fails on Linux Aura, probably because clipboard isn't built yet.
// See http://crbug.com/100347
#if defined(USE_AURA) && !defined(OS_WIN)
#define MAYBE_CutCopyPasteNode FAILS_CutCopyPasteNode
#else
#define MAYBE_CutCopyPasteNode CutCopyPasteNode
#endif
TEST_F(BookmarkContextMenuControllerTest, MAYBE_CutCopyPasteNode) {
  const BookmarkNode* bb_node = model_->bookmark_bar_node();
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(bb_node->GetChild(0));
  scoped_ptr<BookmarkContextMenuController> controller(
      new BookmarkContextMenuController(
          NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes));
  EXPECT_TRUE(controller->IsCommandIdEnabled(IDC_COPY));
  EXPECT_TRUE(controller->IsCommandIdEnabled(IDC_CUT));

  // Copy the URL.
  controller->ExecuteCommand(IDC_COPY);

  controller.reset(new BookmarkContextMenuController(
      NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes));
  int old_count = bb_node->child_count();
  controller->ExecuteCommand(IDC_PASTE);

  ASSERT_TRUE(bb_node->GetChild(1)->is_url());
  ASSERT_EQ(old_count + 1, bb_node->child_count());
  ASSERT_EQ(bb_node->GetChild(0)->url(), bb_node->GetChild(1)->url());

  controller.reset(new BookmarkContextMenuController(
      NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes));
  // Cut the URL.
  controller->ExecuteCommand(IDC_CUT);
  ASSERT_TRUE(bb_node->GetChild(0)->is_url());
  ASSERT_TRUE(bb_node->GetChild(1)->is_folder());
  ASSERT_EQ(old_count, bb_node->child_count());
}
<commit_msg>Enable BookmarkContextMenuControllerTest.CutCopyPasteNode for aura builds.<commit_after>// Copyright (c) 2011 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 <string>

#include "base/memory/scoped_ptr.h"
#include "base/utf_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/bookmarks/bookmark_context_menu_controller.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/test/base/testing_profile.h"
#include "content/browser/browser_thread.h"
#include "content/browser/tab_contents/page_navigator.h"
#include "grit/generated_resources.h"
#include "testing/gtest/include/gtest/gtest.h"

#if defined(OS_WIN)
#include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
#endif

// PageNavigator implementation that records the URL.
class TestingPageNavigator : public PageNavigator {
 public:
  // Deprecated. Please use the one-argument variant.
  // TODO(adriansc): Remove this method once refactoring changed all call
  // sites.
  virtual TabContents* OpenURL(const GURL& url,
                               const GURL& referrer,
                               WindowOpenDisposition disposition,
                               content::PageTransition transition) OVERRIDE {
    return OpenURL(OpenURLParams(url, referrer, disposition, transition,
                                 false));
  }

  virtual TabContents* OpenURL(const OpenURLParams& params) OVERRIDE {
    urls_.push_back(params.url);
    return NULL;
  }

  std::vector<GURL> urls_;
};

class BookmarkContextMenuControllerTest : public testing::Test {
 public:
  BookmarkContextMenuControllerTest()
      : ui_thread_(BrowserThread::UI, &message_loop_),
        file_thread_(BrowserThread::FILE, &message_loop_),
        model_(NULL) {
  }

  virtual void SetUp() {
#if defined(OS_WIN)
    BookmarkBarView::testing_ = true;
#endif

    profile_.reset(new TestingProfile());
    profile_->CreateBookmarkModel(true);
    profile_->BlockUntilBookmarkModelLoaded();

    model_ = profile_->GetBookmarkModel();

    AddTestData();
  }

  virtual void TearDown() {
#if defined(OS_WIN)
    BookmarkBarView::testing_ = false;
#endif

    // Flush the message loop to make application verifiers happy.
    message_loop_.RunAllPending();
  }

 protected:
  MessageLoopForUI message_loop_;
  BrowserThread ui_thread_;
  BrowserThread file_thread_;
  scoped_ptr<TestingProfile> profile_;
  BookmarkModel* model_;
  TestingPageNavigator navigator_;

 private:
  // Creates the following structure:
  // a
  // F1
  //  f1a
  //  F11
  //   f11a
  // F2
  // F3
  // F4
  //   f4a
  void AddTestData() {
    const BookmarkNode* bb_node = model_->bookmark_bar_node();
    std::string test_base = "file:///c:/tmp/";
    model_->AddURL(bb_node, 0, ASCIIToUTF16("a"), GURL(test_base + "a"));
    const BookmarkNode* f1 = model_->AddFolder(bb_node, 1, ASCIIToUTF16("F1"));
    model_->AddURL(f1, 0, ASCIIToUTF16("f1a"), GURL(test_base + "f1a"));
    const BookmarkNode* f11 = model_->AddFolder(f1, 1, ASCIIToUTF16("F11"));
    model_->AddURL(f11, 0, ASCIIToUTF16("f11a"), GURL(test_base + "f11a"));
    model_->AddFolder(bb_node, 2, ASCIIToUTF16("F2"));
    model_->AddFolder(bb_node, 3, ASCIIToUTF16("F3"));
    const BookmarkNode* f4 = model_->AddFolder(bb_node, 4, ASCIIToUTF16("F4"));
    model_->AddURL(f4, 0, ASCIIToUTF16("f4a"), GURL(test_base + "f4a"));
  }
};

// Tests Deleting from the menu.
TEST_F(BookmarkContextMenuControllerTest, DeleteURL) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->bookmark_bar_node()->GetChild(0));
  BookmarkContextMenuController controller(
      NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes);
  GURL url = model_->bookmark_bar_node()->GetChild(0)->url();
  ASSERT_TRUE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_REMOVE));
  // Delete the URL.
  controller.ExecuteCommand(IDC_BOOKMARK_BAR_REMOVE);
  // Model shouldn't have URL anymore.
  ASSERT_FALSE(model_->IsBookmarked(url));
}

// Tests open all on a folder with a couple of bookmarks.
TEST_F(BookmarkContextMenuControllerTest, OpenAll) {
  const BookmarkNode* folder = model_->bookmark_bar_node()->GetChild(1);
  bookmark_utils::OpenAll(
      NULL, profile_.get(), &navigator_, folder, NEW_FOREGROUND_TAB);

  // Should have navigated to F1's child, but not F11's child.
  ASSERT_EQ(static_cast<size_t>(1), navigator_.urls_.size());
  ASSERT_TRUE(folder->GetChild(0)->url() == navigator_.urls_[0]);
}

// Tests the enabled state of the menus when supplied an empty vector.
TEST_F(BookmarkContextMenuControllerTest, EmptyNodes) {
  BookmarkContextMenuController controller(
      NULL, NULL, profile_.get(), NULL, model_->other_node(),
      std::vector<const BookmarkNode*>());
  EXPECT_FALSE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_FALSE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_REMOVE));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of the menus when supplied a vector with a single
// url.
TEST_F(BookmarkContextMenuControllerTest, SingleURL) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->bookmark_bar_node()->GetChild(0));
  BookmarkContextMenuController controller(
      NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes);
  EXPECT_TRUE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_TRUE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_REMOVE));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of the menus when supplied a vector with multiple
// urls.
TEST_F(BookmarkContextMenuControllerTest, MultipleURLs) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->bookmark_bar_node()->GetChild(0));
  nodes.push_back(model_->bookmark_bar_node()->GetChild(1)->GetChild(0));
  BookmarkContextMenuController controller(
      NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes);
  EXPECT_TRUE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_TRUE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_REMOVE));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of the menus when supplied an vector with a single
// folder.
TEST_F(BookmarkContextMenuControllerTest, SingleFolder) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->bookmark_bar_node()->GetChild(2));
  BookmarkContextMenuController controller(
      NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes);
  EXPECT_FALSE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_TRUE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_REMOVE));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of the menus when supplied a vector with multiple
// folders, all of which are empty.
TEST_F(BookmarkContextMenuControllerTest, MultipleEmptyFolders) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->bookmark_bar_node()->GetChild(2));
  nodes.push_back(model_->bookmark_bar_node()->GetChild(3));
  BookmarkContextMenuController controller(
      NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes);
  EXPECT_FALSE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_TRUE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_REMOVE));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of the menus when supplied a vector with multiple
// folders, some of which contain URLs.
TEST_F(BookmarkContextMenuControllerTest, MultipleFoldersWithURLs) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->bookmark_bar_node()->GetChild(3));
  nodes.push_back(model_->bookmark_bar_node()->GetChild(4));
  BookmarkContextMenuController controller(
      NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes);
  EXPECT_TRUE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_TRUE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_REMOVE));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_TRUE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_NEW_FOLDER));
}

// Tests the enabled state of open incognito.
TEST_F(BookmarkContextMenuControllerTest, DisableIncognito) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->bookmark_bar_node()->GetChild(0));
  BookmarkContextMenuController controller(
      NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes);
  profile_->set_incognito(true);
  EXPECT_FALSE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_INCOGNITO));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
}

// Tests that you can't remove/edit when showing the other node.
TEST_F(BookmarkContextMenuControllerTest, DisabledItemsWithOtherNode) {
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(model_->other_node());
  BookmarkContextMenuController controller(
      NULL, NULL, profile_.get(), NULL, nodes[0], nodes);
  EXPECT_FALSE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_EDIT));
  EXPECT_FALSE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_REMOVE));
}

// Tests the enabled state of the menus when supplied an empty vector and null
// parent.
TEST_F(BookmarkContextMenuControllerTest, EmptyNodesNullParent) {
  BookmarkContextMenuController controller(
      NULL, NULL, profile_.get(), NULL, NULL,
      std::vector<const BookmarkNode*>());
  EXPECT_FALSE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_OPEN_ALL_INCOGNITO));
  EXPECT_FALSE(controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_REMOVE));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_ADD_NEW_BOOKMARK));
  EXPECT_FALSE(
      controller.IsCommandIdEnabled(IDC_BOOKMARK_BAR_NEW_FOLDER));
}

TEST_F(BookmarkContextMenuControllerTest, CutCopyPasteNode) {
  const BookmarkNode* bb_node = model_->bookmark_bar_node();
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(bb_node->GetChild(0));
  scoped_ptr<BookmarkContextMenuController> controller(
      new BookmarkContextMenuController(
          NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes));
  EXPECT_TRUE(controller->IsCommandIdEnabled(IDC_COPY));
  EXPECT_TRUE(controller->IsCommandIdEnabled(IDC_CUT));

  // Copy the URL.
  controller->ExecuteCommand(IDC_COPY);

  controller.reset(new BookmarkContextMenuController(
      NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes));
  int old_count = bb_node->child_count();
  controller->ExecuteCommand(IDC_PASTE);

  ASSERT_TRUE(bb_node->GetChild(1)->is_url());
  ASSERT_EQ(old_count + 1, bb_node->child_count());
  ASSERT_EQ(bb_node->GetChild(0)->url(), bb_node->GetChild(1)->url());

  controller.reset(new BookmarkContextMenuController(
      NULL, NULL, profile_.get(), NULL, nodes[0]->parent(), nodes));
  // Cut the URL.
  controller->ExecuteCommand(IDC_CUT);
  ASSERT_TRUE(bb_node->GetChild(0)->is_url());
  ASSERT_TRUE(bb_node->GetChild(1)->is_folder());
  ASSERT_EQ(old_count, bb_node->child_count());
}
<|endoftext|>