<commit_before>
#include <globjects/Program.h>

#include <cassert>

#include <glbinding/gl/functions.h>
#include <glbinding/gl/extension.h>
#include <glbinding/gl/boolean.h>
#include <glbinding/gl/enum.h>

#include <globjects/globjects.h>

#include <globjects/Uniform.h>
#include <globjects/ObjectVisitor.h>
#include <globjects/ProgramBinary.h>
#include <globjects/Shader.h>
#include <globjects/AbstractUniform.h>

#include "Resource.h"
#include "registry/ImplementationRegistry.h"
#include "implementations/AbstractProgramBinaryImplementation.h"

using namespace gl;

namespace
{

const globjects::AbstractProgramBinaryImplementation & binaryImplementation()
{
    return globjects::ImplementationRegistry::current().programBinaryImplementation();
}

}

namespace globjects
{

void Program::hintBinaryImplementation(const BinaryImplementation impl)
{
    ImplementationRegistry::current().initialize(impl);
}

Program::Program()
: Object(new ProgramResource)
, m_linked(false)
, m_dirty(true)
{
}

Program::Program(ProgramBinary * binary)
: Program()
{
    setBinary(binary);
}

Program::~Program()
{
    for (std::pair<LocationIdentity, ref_ptr<AbstractUniform>> uniformPair : m_uniforms)
        uniformPair.second->deregisterProgram(this);

    if (0 == id())
    {
        for (auto & shader : m_shaders)
            shader->deregisterListener(this);
    }
    else
    {
        for (ref_ptr<Shader> shader : std::set<ref_ptr<Shader>>(m_shaders))
            detach(shader);
    }
}

void Program::accept(ObjectVisitor & visitor)
{
	visitor.visitProgram(this);
}

void Program::use() const
{
	checkDirty();

    if (!isLinked())
        return;

    glUseProgram(id());
}

void Program::release() const
{
    if (!isLinked())
        return;

    glUseProgram(0);
}

bool Program::isUsed() const
{
    GLuint currentProgram = static_cast<GLuint>(getInteger(GL_CURRENT_PROGRAM));

    return currentProgram > 0 && currentProgram == id();
}

bool Program::isLinked() const
{
	return m_linked;
}

void Program::invalidate() const
{
	m_dirty = true;
}

void Program::notifyChanged(const Changeable *)
{
	invalidate();
}

void Program::checkDirty() const
{
    if (m_dirty)
        link();
}

void Program::attach(Shader * shader)
{
    assert(shader != nullptr);

    gl::glAttachShader(id(), shader->id());

    shader->registerListener(this);
    m_shaders.insert(shader);

    invalidate();
}

void Program::detach(Shader * shader)
{
    assert(shader != nullptr);

    glDetachShader(id(), shader->id());

	shader->deregisterListener(this);
	m_shaders.erase(shader);

	invalidate();
}

std::set<Shader *> Program::shaders() const
{
	std::set<Shader *> shaders;
    for (ref_ptr<Shader> shader: m_shaders)
		shaders.insert(shader);
	return shaders;
}

void Program::link() const
{
    m_linked = false;

    if (!binaryImplementation().updateProgramLinkSource(this))
        return;

    glLinkProgram(id());

    m_linked = checkLinkStatus();
	m_dirty = false;

    updateUniforms();
    updateUniformBlockBindings();
}

bool Program::compileAttachedShaders() const
{
    for (Shader * shader : shaders())
    {
        if (shader->isCompiled())
            continue;

        // Some drivers (e.g. nvidia-331 on Ubuntu 13.04 automatically compile shaders during program linkage)
        // but we don't want to depend on such behavior
        shader->compile();

        if (!shader->isCompiled())
            return false;
    }
    return true;
}

bool Program::checkLinkStatus() const
{
    if (GL_FALSE == static_cast<GLboolean>(get(GL_LINK_STATUS)))
    {
        critical() << "Linker error:" << std::endl << infoLog();
        return false;
    }
    return true;
}

void Program::bindFragDataLocation(const GLuint index, const std::string & name) const
{
    glBindFragDataLocation(id(), index, name.c_str());
}

void Program::bindAttributeLocation(const GLuint index, const std::string & name) const
{
    glBindAttribLocation(id(), index, name.c_str());
}

GLint Program::getFragDataLocation(const std::string & name) const
{
    return glGetFragDataLocation(id(), name.c_str());
}

GLint Program::getFragDataIndex(const std::string & name) const
{
    return glGetFragDataIndex(id(), name.c_str());
}

GLint Program::getUniformLocation(const std::string& name) const
{
	checkDirty();
    if (!m_linked)
        return -1;

    return glGetUniformLocation(id(), name.c_str());
}

std::vector<GLint> Program::getAttributeLocations(const std::vector<std::string> & names) const
{
    std::vector<GLint> locations(names.size());
    for (unsigned i = 0; i<names.size(); ++i)
    {
        locations[i] = getAttributeLocation(names[i]);
    }
    return locations;
}

std::vector<GLint> Program::getUniformLocations(const std::vector<std::string> & names) const
{
    std::vector<GLint> locations(names.size());
    for (unsigned i = 0; i<names.size(); ++i)
    {
        locations[i] = getUniformLocation(names[i]);
    }
    return locations;
}

GLint Program::getAttributeLocation(const std::string & name) const
{
	checkDirty();
    if (!m_linked)
        return -1;

    return glGetAttribLocation(id(), name.c_str());
}

void Program::getInterface(gl::GLenum programInterface, gl::GLenum pname, gl::GLint * params) const
{
    checkDirty();

    glGetProgramInterfaceiv(id(), programInterface, pname, params);
}

GLuint Program::getResourceIndex(const GLenum programInterface, const std::string & name) const
{
    checkDirty();

    return glGetProgramResourceIndex(id(), programInterface, name.data());
}

void Program::getResourceName(gl::GLenum programInterface, gl::GLuint index, gl::GLsizei bufSize, gl::GLsizei * length, char * name)
{
    checkDirty();

    glGetProgramResourceName(id(), programInterface, index, bufSize, length, name);
}

void Program::getResource(gl::GLenum programInterface, gl::GLuint index, gl::GLsizei propCount, const gl::GLenum * props, gl::GLsizei bufSize, gl::GLsizei * length, gl::GLint * params)
{
    checkDirty();

    glGetProgramResourceiv(id(), programInterface, index, propCount, props, bufSize, length, params);
}

gl::GLint Program::getResourceLocation(gl::GLenum programInterface, const std::string & name)
{
    checkDirty();

    return glGetProgramResourceLocation(id(), programInterface, name.data());
}

gl::GLint Program::getResourceLocationIndex(gl::GLenum programInterface, const std::string & name)
{
    checkDirty();

    return glGetProgramResourceLocationIndex(id(), programInterface, name.data());
}

gl::GLint Program::getResource(gl::GLenum programInterface, gl::GLuint index, gl::GLenum prop, gl::GLsizei * length)
{
    gl::GLint result;

    getResource(programInterface, index, 1, &prop, 1, length, &result);

    return result;
}

std::vector<gl::GLint> Program::getResource(gl::GLenum programInterface, gl::GLuint index, const std::vector<gl::GLenum> & props, gl::GLsizei * length)
{
    std::vector<gl::GLint> result;
    result.resize(props.size());

    getResource(programInterface, index, props, result.size(), length, result.data());

    return result;
}

void Program::getResource(gl::GLenum programInterface, gl::GLuint index, const std::vector<gl::GLenum> & props, gl::GLsizei bufSize, gl::GLsizei * length, gl::GLint * params)
{
    getResource(programInterface, index, props.size(), props.data(), bufSize, length, params);
}

std::string Program::getResourceName(gl::GLenum programInterface, gl::GLuint index)
{
    std::vector<char> result;

    size_t nameLength = getResource(programInterface, index, gl::GL_NAME_LENGTH);
    result.resize(nameLength + 1);

#ifndef NDEBUG
    gl::GLint length;
    getResourceName(programInterface, index, nameLength, &length, result.data());
    assert(length + 1 == static_cast<gl::GLint>(nameLength)); // length does NOT include the null-terminator
#else
    getResourceName(programInterface, index, nameLength, NULL, result.data());
#endif

    return std::string(result.data(), nameLength);
}

GLuint Program::getUniformBlockIndex(const std::string & name) const
{
    checkDirty();

    return glGetUniformBlockIndex(id(), name.c_str());
}

void Program::getActiveUniforms(const GLsizei uniformCount, const GLuint * uniformIndices, const GLenum pname, GLint * params) const
{
    checkDirty();

    glGetActiveUniformsiv(id(), uniformCount, uniformIndices, pname, params);
}

std::vector<GLint> Program::getActiveUniforms(const std::vector<GLuint> & uniformIndices, const GLenum pname) const
{
    std::vector<GLint> result(uniformIndices.size());
    getActiveUniforms(static_cast<GLint>(uniformIndices.size()), uniformIndices.data(), pname, result.data());
    return result;
}

std::vector<GLint> Program::getActiveUniforms(const std::vector<GLint> & uniformIndices, const GLenum pname) const
{
    std::vector<GLuint> indices(uniformIndices.size());
    for (unsigned i=0; i<uniformIndices.size(); ++i)
        indices[i] = static_cast<GLuint>(uniformIndices[i]);
    return getActiveUniforms(indices, pname);
}

GLint Program::getActiveUniform(const GLuint uniformIndex, const GLenum pname) const
{
    GLint result = 0;
    getActiveUniforms(1, &uniformIndex, pname, &result);
    return result;
}

std::string Program::getActiveUniformName(const GLuint uniformIndex) const
{
    checkDirty();

    GLint length = getActiveUniform(uniformIndex, GL_UNIFORM_NAME_LENGTH);
    std::vector<char> name(length);
    glGetActiveUniformName(id(), uniformIndex, length, nullptr, name.data());

    return std::string(name.data(), length);
}

UniformBlock * Program::uniformBlock(const GLuint uniformBlockIndex)
{
    return getUniformBlockByIdentity(uniformBlockIndex);
}

UniformBlock * Program::uniformBlock(const std::string& name)
{
    return getUniformBlockByIdentity(name);
}

UniformBlock * Program::getUniformBlockByIdentity(const LocationIdentity & identity)
{
    checkDirty();

    if (m_uniformBlocks.find(identity) == m_uniformBlocks.end())
        m_uniformBlocks[identity] = UniformBlock(this, identity);

    return &m_uniformBlocks[identity];
}

void Program::addUniform(AbstractUniform * uniform)
{
    assert(uniform != nullptr);

    ref_ptr<AbstractUniform>& uniformReference = m_uniforms[uniform->identity()];

	if (uniformReference)
		uniformReference->deregisterProgram(this);

	uniformReference = uniform;

	uniform->registerProgram(this);

	if (m_linked)
		uniform->update(this);
}

void Program::updateUniforms() const
{
	// Note: uniform update will check if program is linked
    for (std::pair<LocationIdentity, ref_ptr<AbstractUniform>> uniformPair : m_uniforms)
		uniformPair.second->update(this);
}

void Program::updateUniformBlockBindings() const
{
    for (std::pair<LocationIdentity, UniformBlock> pair : m_uniformBlocks)
        pair.second.updateBinding();
}

void Program::setBinary(ProgramBinary * binary)
{
    if (m_binary == binary)
        return;

    if (m_binary)
        m_binary->deregisterListener(this);

    m_binary = binary;

    if (m_binary)
        m_binary->registerListener(this);
}

ProgramBinary * Program::getBinary() const
{
    return binaryImplementation().getProgramBinary(this);
}

GLint Program::get(const GLenum pname) const
{
    GLint value = 0;
    glGetProgramiv(id(), pname, &value);

	return value;
}

const std::string Program::infoLog() const
{
    GLint length = get(GL_INFO_LOG_LENGTH);

    if (length == 0)
        return std::string();

    std::vector<char> log(length);

    glGetProgramInfoLog(id(), length, &length, log.data());

	return std::string(log.data(), length);
}

void Program::dispatchCompute(const glm::uvec3 & numGroups)
{
    dispatchCompute(numGroups.x, numGroups.y, numGroups.z);
}

void Program::dispatchCompute(const GLuint numGroupsX, const GLuint numGroupsY, const GLuint numGroupsZ)
{
    use();

    if (!m_linked)
        return;

    glDispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
}

void Program::dispatchComputeGroupSize(const GLuint numGroupsX, const GLuint numGroupsY, const GLuint numGroupsZ, const GLuint groupSizeX, const GLuint groupSizeY, const GLuint groupSizeZ)
{
    use();

    if (!m_linked)
        return;

    glDispatchComputeGroupSizeARB(numGroupsX, numGroupsY, numGroupsZ, groupSizeX, groupSizeY, groupSizeZ);
}

void Program::dispatchComputeGroupSize(const glm::uvec3 & numGroups, const glm::uvec3 & groupSizes)
{
    dispatchComputeGroupSize(numGroups.x, numGroups.y, numGroups.z, groupSizes.x, groupSizes.y, groupSizes.z);
}

void Program::setShaderStorageBlockBinding(const GLuint storageBlockIndex, const GLuint storageBlockBinding) const
{
	checkDirty();
    if (!m_linked)
        return;

    glShaderStorageBlockBinding(id(), storageBlockIndex, storageBlockBinding);
}

GLenum Program::objectType() const
{
    return GL_PROGRAM;
}

} // namespace globjects
<commit_msg>Program::getResourceName(): Early out if nameLength == 0, #267<commit_after>
#include <globjects/Program.h>

#include <cassert>

#include <glbinding/gl/functions.h>
#include <glbinding/gl/extension.h>
#include <glbinding/gl/boolean.h>
#include <glbinding/gl/enum.h>

#include <globjects/globjects.h>

#include <globjects/Uniform.h>
#include <globjects/ObjectVisitor.h>
#include <globjects/ProgramBinary.h>
#include <globjects/Shader.h>
#include <globjects/AbstractUniform.h>

#include "Resource.h"
#include "registry/ImplementationRegistry.h"
#include "implementations/AbstractProgramBinaryImplementation.h"

using namespace gl;

namespace
{

const globjects::AbstractProgramBinaryImplementation & binaryImplementation()
{
    return globjects::ImplementationRegistry::current().programBinaryImplementation();
}

}

namespace globjects
{

void Program::hintBinaryImplementation(const BinaryImplementation impl)
{
    ImplementationRegistry::current().initialize(impl);
}

Program::Program()
: Object(new ProgramResource)
, m_linked(false)
, m_dirty(true)
{
}

Program::Program(ProgramBinary * binary)
: Program()
{
    setBinary(binary);
}

Program::~Program()
{
    for (std::pair<LocationIdentity, ref_ptr<AbstractUniform>> uniformPair : m_uniforms)
        uniformPair.second->deregisterProgram(this);

    if (0 == id())
    {
        for (auto & shader : m_shaders)
            shader->deregisterListener(this);
    }
    else
    {
        for (ref_ptr<Shader> shader : std::set<ref_ptr<Shader>>(m_shaders))
            detach(shader);
    }
}

void Program::accept(ObjectVisitor & visitor)
{
	visitor.visitProgram(this);
}

void Program::use() const
{
	checkDirty();

    if (!isLinked())
        return;

    glUseProgram(id());
}

void Program::release() const
{
    if (!isLinked())
        return;

    glUseProgram(0);
}

bool Program::isUsed() const
{
    GLuint currentProgram = static_cast<GLuint>(getInteger(GL_CURRENT_PROGRAM));

    return currentProgram > 0 && currentProgram == id();
}

bool Program::isLinked() const
{
	return m_linked;
}

void Program::invalidate() const
{
	m_dirty = true;
}

void Program::notifyChanged(const Changeable *)
{
	invalidate();
}

void Program::checkDirty() const
{
    if (m_dirty)
        link();
}

void Program::attach(Shader * shader)
{
    assert(shader != nullptr);

    gl::glAttachShader(id(), shader->id());

    shader->registerListener(this);
    m_shaders.insert(shader);

    invalidate();
}

void Program::detach(Shader * shader)
{
    assert(shader != nullptr);

    glDetachShader(id(), shader->id());

	shader->deregisterListener(this);
	m_shaders.erase(shader);

	invalidate();
}

std::set<Shader *> Program::shaders() const
{
	std::set<Shader *> shaders;
    for (ref_ptr<Shader> shader: m_shaders)
		shaders.insert(shader);
	return shaders;
}

void Program::link() const
{
    m_linked = false;

    if (!binaryImplementation().updateProgramLinkSource(this))
        return;

    glLinkProgram(id());

    m_linked = checkLinkStatus();
	m_dirty = false;

    updateUniforms();
    updateUniformBlockBindings();
}

bool Program::compileAttachedShaders() const
{
    for (Shader * shader : shaders())
    {
        if (shader->isCompiled())
            continue;

        // Some drivers (e.g. nvidia-331 on Ubuntu 13.04 automatically compile shaders during program linkage)
        // but we don't want to depend on such behavior
        shader->compile();

        if (!shader->isCompiled())
            return false;
    }
    return true;
}

bool Program::checkLinkStatus() const
{
    if (GL_FALSE == static_cast<GLboolean>(get(GL_LINK_STATUS)))
    {
        critical() << "Linker error:" << std::endl << infoLog();
        return false;
    }
    return true;
}

void Program::bindFragDataLocation(const GLuint index, const std::string & name) const
{
    glBindFragDataLocation(id(), index, name.c_str());
}

void Program::bindAttributeLocation(const GLuint index, const std::string & name) const
{
    glBindAttribLocation(id(), index, name.c_str());
}

GLint Program::getFragDataLocation(const std::string & name) const
{
    return glGetFragDataLocation(id(), name.c_str());
}

GLint Program::getFragDataIndex(const std::string & name) const
{
    return glGetFragDataIndex(id(), name.c_str());
}

GLint Program::getUniformLocation(const std::string& name) const
{
	checkDirty();
    if (!m_linked)
        return -1;

    return glGetUniformLocation(id(), name.c_str());
}

std::vector<GLint> Program::getAttributeLocations(const std::vector<std::string> & names) const
{
    std::vector<GLint> locations(names.size());
    for (unsigned i = 0; i<names.size(); ++i)
    {
        locations[i] = getAttributeLocation(names[i]);
    }
    return locations;
}

std::vector<GLint> Program::getUniformLocations(const std::vector<std::string> & names) const
{
    std::vector<GLint> locations(names.size());
    for (unsigned i = 0; i<names.size(); ++i)
    {
        locations[i] = getUniformLocation(names[i]);
    }
    return locations;
}

GLint Program::getAttributeLocation(const std::string & name) const
{
	checkDirty();
    if (!m_linked)
        return -1;

    return glGetAttribLocation(id(), name.c_str());
}

void Program::getInterface(gl::GLenum programInterface, gl::GLenum pname, gl::GLint * params) const
{
    checkDirty();

    glGetProgramInterfaceiv(id(), programInterface, pname, params);
}

GLuint Program::getResourceIndex(const GLenum programInterface, const std::string & name) const
{
    checkDirty();

    return glGetProgramResourceIndex(id(), programInterface, name.data());
}

void Program::getResourceName(gl::GLenum programInterface, gl::GLuint index, gl::GLsizei bufSize, gl::GLsizei * length, char * name)
{
    checkDirty();

    glGetProgramResourceName(id(), programInterface, index, bufSize, length, name);
}

void Program::getResource(gl::GLenum programInterface, gl::GLuint index, gl::GLsizei propCount, const gl::GLenum * props, gl::GLsizei bufSize, gl::GLsizei * length, gl::GLint * params)
{
    checkDirty();

    glGetProgramResourceiv(id(), programInterface, index, propCount, props, bufSize, length, params);
}

gl::GLint Program::getResourceLocation(gl::GLenum programInterface, const std::string & name)
{
    checkDirty();

    return glGetProgramResourceLocation(id(), programInterface, name.data());
}

gl::GLint Program::getResourceLocationIndex(gl::GLenum programInterface, const std::string & name)
{
    checkDirty();

    return glGetProgramResourceLocationIndex(id(), programInterface, name.data());
}

gl::GLint Program::getResource(gl::GLenum programInterface, gl::GLuint index, gl::GLenum prop, gl::GLsizei * length)
{
    gl::GLint result;

    getResource(programInterface, index, 1, &prop, 1, length, &result);

    return result;
}

std::vector<gl::GLint> Program::getResource(gl::GLenum programInterface, gl::GLuint index, const std::vector<gl::GLenum> & props, gl::GLsizei * length)
{
    std::vector<gl::GLint> result;
    result.resize(props.size());

    getResource(programInterface, index, props, result.size(), length, result.data());

    return result;
}

void Program::getResource(gl::GLenum programInterface, gl::GLuint index, const std::vector<gl::GLenum> & props, gl::GLsizei bufSize, gl::GLsizei * length, gl::GLint * params)
{
    getResource(programInterface, index, props.size(), props.data(), bufSize, length, params);
}

std::string Program::getResourceName(gl::GLenum programInterface, gl::GLuint index)
{
    std::vector<char> result;

    size_t nameLength = getResource(programInterface, index, gl::GL_NAME_LENGTH);

    if (nameLength == 0)
        return std::string();

    result.resize(nameLength + 1);

#ifndef NDEBUG
    gl::GLint length;
    getResourceName(programInterface, index, nameLength, &length, result.data());
    assert(length + 1 == static_cast<gl::GLint>(nameLength)); // length does NOT include the null-terminator
#else
    getResourceName(programInterface, index, nameLength, NULL, result.data());
#endif

    return std::string(result.data(), nameLength);
}

GLuint Program::getUniformBlockIndex(const std::string & name) const
{
    checkDirty();

    return glGetUniformBlockIndex(id(), name.c_str());
}

void Program::getActiveUniforms(const GLsizei uniformCount, const GLuint * uniformIndices, const GLenum pname, GLint * params) const
{
    checkDirty();

    glGetActiveUniformsiv(id(), uniformCount, uniformIndices, pname, params);
}

std::vector<GLint> Program::getActiveUniforms(const std::vector<GLuint> & uniformIndices, const GLenum pname) const
{
    std::vector<GLint> result(uniformIndices.size());
    getActiveUniforms(static_cast<GLint>(uniformIndices.size()), uniformIndices.data(), pname, result.data());
    return result;
}

std::vector<GLint> Program::getActiveUniforms(const std::vector<GLint> & uniformIndices, const GLenum pname) const
{
    std::vector<GLuint> indices(uniformIndices.size());
    for (unsigned i=0; i<uniformIndices.size(); ++i)
        indices[i] = static_cast<GLuint>(uniformIndices[i]);
    return getActiveUniforms(indices, pname);
}

GLint Program::getActiveUniform(const GLuint uniformIndex, const GLenum pname) const
{
    GLint result = 0;
    getActiveUniforms(1, &uniformIndex, pname, &result);
    return result;
}

std::string Program::getActiveUniformName(const GLuint uniformIndex) const
{
    checkDirty();

    GLint length = getActiveUniform(uniformIndex, GL_UNIFORM_NAME_LENGTH);
    std::vector<char> name(length);
    glGetActiveUniformName(id(), uniformIndex, length, nullptr, name.data());

    return std::string(name.data(), length);
}

UniformBlock * Program::uniformBlock(const GLuint uniformBlockIndex)
{
    return getUniformBlockByIdentity(uniformBlockIndex);
}

UniformBlock * Program::uniformBlock(const std::string& name)
{
    return getUniformBlockByIdentity(name);
}

UniformBlock * Program::getUniformBlockByIdentity(const LocationIdentity & identity)
{
    checkDirty();

    if (m_uniformBlocks.find(identity) == m_uniformBlocks.end())
        m_uniformBlocks[identity] = UniformBlock(this, identity);

    return &m_uniformBlocks[identity];
}

void Program::addUniform(AbstractUniform * uniform)
{
    assert(uniform != nullptr);

    ref_ptr<AbstractUniform>& uniformReference = m_uniforms[uniform->identity()];

	if (uniformReference)
		uniformReference->deregisterProgram(this);

	uniformReference = uniform;

	uniform->registerProgram(this);

	if (m_linked)
		uniform->update(this);
}

void Program::updateUniforms() const
{
	// Note: uniform update will check if program is linked
    for (std::pair<LocationIdentity, ref_ptr<AbstractUniform>> uniformPair : m_uniforms)
		uniformPair.second->update(this);
}

void Program::updateUniformBlockBindings() const
{
    for (std::pair<LocationIdentity, UniformBlock> pair : m_uniformBlocks)
        pair.second.updateBinding();
}

void Program::setBinary(ProgramBinary * binary)
{
    if (m_binary == binary)
        return;

    if (m_binary)
        m_binary->deregisterListener(this);

    m_binary = binary;

    if (m_binary)
        m_binary->registerListener(this);
}

ProgramBinary * Program::getBinary() const
{
    return binaryImplementation().getProgramBinary(this);
}

GLint Program::get(const GLenum pname) const
{
    GLint value = 0;
    glGetProgramiv(id(), pname, &value);

	return value;
}

const std::string Program::infoLog() const
{
    GLint length = get(GL_INFO_LOG_LENGTH);

    if (length == 0)
        return std::string();

    std::vector<char> log(length);

    glGetProgramInfoLog(id(), length, &length, log.data());

	return std::string(log.data(), length);
}

void Program::dispatchCompute(const glm::uvec3 & numGroups)
{
    dispatchCompute(numGroups.x, numGroups.y, numGroups.z);
}

void Program::dispatchCompute(const GLuint numGroupsX, const GLuint numGroupsY, const GLuint numGroupsZ)
{
    use();

    if (!m_linked)
        return;

    glDispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
}

void Program::dispatchComputeGroupSize(const GLuint numGroupsX, const GLuint numGroupsY, const GLuint numGroupsZ, const GLuint groupSizeX, const GLuint groupSizeY, const GLuint groupSizeZ)
{
    use();

    if (!m_linked)
        return;

    glDispatchComputeGroupSizeARB(numGroupsX, numGroupsY, numGroupsZ, groupSizeX, groupSizeY, groupSizeZ);
}

void Program::dispatchComputeGroupSize(const glm::uvec3 & numGroups, const glm::uvec3 & groupSizes)
{
    dispatchComputeGroupSize(numGroups.x, numGroups.y, numGroups.z, groupSizes.x, groupSizes.y, groupSizes.z);
}

void Program::setShaderStorageBlockBinding(const GLuint storageBlockIndex, const GLuint storageBlockBinding) const
{
	checkDirty();
    if (!m_linked)
        return;

    glShaderStorageBlockBinding(id(), storageBlockIndex, storageBlockBinding);
}

GLenum Program::objectType() const
{
    return GL_PROGRAM;
}

} // namespace globjects
<|endoftext|>


<commit_before>#ifndef PLATE2D_HPP
#define PLATE2D_HPP
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
    #include <wx/wx.h>
#endif
#include <wx/datetime.h>

#include <vector>
#include <functional>
#include "Plater.hpp"
#include "ColorScheme.hpp"
#include "Settings.hpp"
#include "Plater/PlaterObject.hpp"
#include "misc_ui.hpp"

#include "Log.hpp"

namespace Slic3r { namespace GUI {

// Setup for an Easter Egg with the canvas text.
const wxDateTime today_date {wxDateTime().GetDateOnly()};
const wxDateTime special_date {13, wxDateTime::Month::Sep, 2006, 0, 0, 0, 0};
const bool today_is_special = {today_date.GetDay() == special_date.GetDay() && today_date.GetMonth() == special_date.GetMonth()};

enum class MoveDirection {
    Up, Down, Left, Right
};

class Plate2D : public wxPanel {
public:
    Plate2D(wxWindow* parent, const wxSize& size, std::vector<PlaterObject>& _objects, std::shared_ptr<Model> _model, std::shared_ptr<Config> _config, std::shared_ptr<Settings> _settings);

//    std::function<> on_select_object {};
private:
    std::vector<PlaterObject>& objects; //< reference to parent vector
    std::shared_ptr<Slic3r::Model> model;
    std::shared_ptr<Slic3r::Config> config;
    std::shared_ptr<Settings> settings;

    // Different brushes to draw with, initialized from settings->Color during the constructor
    wxBrush objects_brush {};
    wxBrush instance_brush {};
    wxBrush selected_brush {};
    wxBrush bed_brush {};
    wxBrush dragged_brush {};
    wxBrush transparent_brush {};

    wxPen grid_pen {};
    wxPen print_center_pen {};
    wxPen clearance_pen {};
    wxPen skirt_pen {};
    wxPen dark_pen {};

    bool user_drawn_background {(the_os == OS::Mac ? false : true)};
    size_t selected_instance;

    /// Handle mouse-move events
    void mouse_drag(wxMouseEvent& e);
    void mouse_down(wxMouseEvent& e);
    void mouse_up(wxMouseEvent& e);
    void mouse_dclick(wxMouseEvent& e);

    /// Handle repaint events
    void repaint(wxPaintEvent& e);

    void nudge_key(wxKeyEvent& e);

    void nudge(MoveDirection dir);

    /// Set/Update all of the colors used by the various brushes in the panel.
    void set_colors();

    /// Convert a scale point array to a pixel polygon suitable for DrawPolygon
    std::vector<wxPoint> scaled_points_to_pixel(const Slic3r::Polygon& poly, bool unscale);
    std::vector<wxPoint> scaled_points_to_pixel(const Slic3r::Polyline& poly, bool unscale);

    /// For a specific point, unscale it relative to the origin
    wxPoint unscaled_point_to_pixel(const wxPoint& in);

    /// Read print bed size from config and calculate the scaled rendition of the bed given the draw canvas.
    void update_bed_size();

    /// private class variables to stash bits for drawing the print bed area.
    wxRealPoint bed_origin {};
    wxRealPoint print_center {};
    Slic3r::Polygon bed_polygon {};
    std::vector<wxPoint> grid {};

    /// Set up the 2D canvas blank canvas text.
    /// Easter egg: Sept. 13, 2006. The first part ever printed by a RepRap to make another RepRap.
    const wxString CANVAS_TEXT { today_is_special ? _(L"What do you want to print today?™") : _("Drag your objects here") };

    /// How much to scale the points to fit in the draw bounding box area.
    /// Expressed as pixel / mm
    double scaling_factor {1.0};

    const std::string LogChannel {"GUI_2D"};

    Slic3r::Point point_to_model_units(coordf_t x, coordf_t y) {
        const auto& zero {this->bed_origin};
        return Slic3r::Point(
            scale_(x - zero.x) / this->scaling_factor,
            scale_(y - zero.y) / this->scaling_factor
        );
    }
    Slic3r::Point point_to_model_units(const wxPoint& pt) {
        return this->point_to_model_units(pt.x, pt.y);
    }
    Slic3r::Point point_to_model_units(const Pointf& pt) {
        return this->point_to_model_units(pt.x, pt.y);
    }

    /// Remove all instance thumbnails.
    void clean_instance_thumbnails();

};

} } // Namespace Slic3r::GUI
#endif // PLATE2D_HPP
<commit_msg>Make update_bed_size() public.<commit_after>#ifndef PLATE2D_HPP
#define PLATE2D_HPP
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
    #include <wx/wx.h>
#endif
#include <wx/datetime.h>

#include <vector>
#include <functional>
#include "Plater.hpp"
#include "ColorScheme.hpp"
#include "Settings.hpp"
#include "Plater/PlaterObject.hpp"
#include "misc_ui.hpp"

#include "Log.hpp"

namespace Slic3r { namespace GUI {

// Setup for an Easter Egg with the canvas text.
const wxDateTime today_date {wxDateTime().GetDateOnly()};
const wxDateTime special_date {13, wxDateTime::Month::Sep, 2006, 0, 0, 0, 0};
const bool today_is_special = {today_date.GetDay() == special_date.GetDay() && today_date.GetMonth() == special_date.GetMonth()};

enum class MoveDirection {
    Up, Down, Left, Right
};

class Plate2D : public wxPanel {
public:
    Plate2D(wxWindow* parent, const wxSize& size, std::vector<PlaterObject>& _objects, std::shared_ptr<Model> _model, std::shared_ptr<Config> _config, std::shared_ptr<Settings> _settings);

    /// Read print bed size from config and calculate the scaled rendition of the bed given the draw canvas.
    void update_bed_size();
//    std::function<> on_select_object {};
private:
    std::vector<PlaterObject>& objects; //< reference to parent vector
    std::shared_ptr<Slic3r::Model> model;
    std::shared_ptr<Slic3r::Config> config;
    std::shared_ptr<Settings> settings;

    // Different brushes to draw with, initialized from settings->Color during the constructor
    wxBrush objects_brush {};
    wxBrush instance_brush {};
    wxBrush selected_brush {};
    wxBrush bed_brush {};
    wxBrush dragged_brush {};
    wxBrush transparent_brush {};

    wxPen grid_pen {};
    wxPen print_center_pen {};
    wxPen clearance_pen {};
    wxPen skirt_pen {};
    wxPen dark_pen {};

    bool user_drawn_background {(the_os == OS::Mac ? false : true)};
    size_t selected_instance;

    /// Handle mouse-move events
    void mouse_drag(wxMouseEvent& e);
    void mouse_down(wxMouseEvent& e);
    void mouse_up(wxMouseEvent& e);
    void mouse_dclick(wxMouseEvent& e);

    /// Handle repaint events
    void repaint(wxPaintEvent& e);

    void nudge_key(wxKeyEvent& e);

    void nudge(MoveDirection dir);

    /// Set/Update all of the colors used by the various brushes in the panel.
    void set_colors();

    /// Convert a scale point array to a pixel polygon suitable for DrawPolygon
    std::vector<wxPoint> scaled_points_to_pixel(const Slic3r::Polygon& poly, bool unscale);
    std::vector<wxPoint> scaled_points_to_pixel(const Slic3r::Polyline& poly, bool unscale);

    /// For a specific point, unscale it relative to the origin
    wxPoint unscaled_point_to_pixel(const wxPoint& in);

    /// private class variables to stash bits for drawing the print bed area.
    wxRealPoint bed_origin {};
    wxRealPoint print_center {};
    Slic3r::Polygon bed_polygon {};
    std::vector<wxPoint> grid {};

    /// Set up the 2D canvas blank canvas text.
    /// Easter egg: Sept. 13, 2006. The first part ever printed by a RepRap to make another RepRap.
    const wxString CANVAS_TEXT { today_is_special ? _(L"What do you want to print today?™") : _("Drag your objects here") };

    /// How much to scale the points to fit in the draw bounding box area.
    /// Expressed as pixel / mm
    double scaling_factor {1.0};

    const std::string LogChannel {"GUI_2D"};

    Slic3r::Point point_to_model_units(coordf_t x, coordf_t y) {
        const auto& zero {this->bed_origin};
        return Slic3r::Point(
            scale_(x - zero.x) / this->scaling_factor,
            scale_(y - zero.y) / this->scaling_factor
        );
    }
    Slic3r::Point point_to_model_units(const wxPoint& pt) {
        return this->point_to_model_units(pt.x, pt.y);
    }
    Slic3r::Point point_to_model_units(const Pointf& pt) {
        return this->point_to_model_units(pt.x, pt.y);
    }

    /// Remove all instance thumbnails.
    void clean_instance_thumbnails();

};

} } // Namespace Slic3r::GUI
#endif // PLATE2D_HPP
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "voice_engine/include/voe_encryption.h"
#include "voice_engine/test/auto_test/fixtures/after_streaming_fixture.h"

class BasicBitInverseEncryption : public webrtc::Encryption {
  void encrypt(int channel_no, unsigned char* in_data,
               unsigned char* out_data, int bytes_in, int* bytes_out);
  void decrypt(int channel_no, unsigned char* in_data,
               unsigned char* out_data, int bytes_in, int* bytes_out);
  void encrypt_rtcp(int channel_no, unsigned char* in_data,
                    unsigned char* out_data, int bytes_in, int* bytes_out);
  void decrypt_rtcp(int channel_no, unsigned char* in_data,
                    unsigned char* out_data, int bytes_in, int* bytes_out);
};

void BasicBitInverseEncryption::encrypt(int, unsigned char* in_data,
                                        unsigned char* out_data,
                                        int bytes_in, int* bytes_out) {
  int i;
  for (i = 0; i < bytes_in; i++)
    out_data[i] = ~in_data[i];
  out_data[bytes_in] = 0;
  out_data[bytes_in + 1] = 0;
  *bytes_out = bytes_in + 2;
}

void BasicBitInverseEncryption::decrypt(int, unsigned char* in_data,
                                        unsigned char* out_data,
                                        int bytes_in, int* bytes_out) {
  int i;
  for (i = 0; i < bytes_in; i++)
    out_data[i] = ~in_data[i];
  *bytes_out = bytes_in - 2;
}

void BasicBitInverseEncryption::encrypt_rtcp(int, unsigned char* in_data,
                                             unsigned char* out_data,
                                             int bytes_in, int* bytes_out) {
  int i;
  for (i = 0; i < bytes_in; i++)
    out_data[i] = ~in_data[i];
  out_data[bytes_in] = 0;
  out_data[bytes_in + 1] = 0;
  *bytes_out = bytes_in + 2;
}

void BasicBitInverseEncryption::decrypt_rtcp(int, unsigned char* in_data,
                                             unsigned char* out_data,
                                             int bytes_in, int* bytes_out) {
  int i;
  for (i = 0; i < bytes_in; i++)
    out_data[i] = ~in_data[i];
  out_data[bytes_in] = 0;
  out_data[bytes_in + 1] = 0;
  *bytes_out = bytes_in + 2;
}

class EncryptionTest : public AfterStreamingFixture {
};

TEST_F(EncryptionTest, ManualBasicCorrectExternalEncryptionHasNoEffectOnVoice) {
  BasicBitInverseEncryption basic_encryption;

  voe_encrypt_->RegisterExternalEncryption(channel_, basic_encryption);

  TEST_LOG("Registered external encryption, should still hear good audio.");
  Sleep(3000);

  voe_encrypt_->DeRegisterExternalEncryption(channel_);
}
<commit_msg>Added last (?) suppressions for known issues.<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "voice_engine/include/voe_encryption.h"
#include "voice_engine/test/auto_test/fixtures/after_streaming_fixture.h"

class BasicBitInverseEncryption : public webrtc::Encryption {
  void encrypt(int channel_no, unsigned char* in_data,
               unsigned char* out_data, int bytes_in, int* bytes_out);
  void decrypt(int channel_no, unsigned char* in_data,
               unsigned char* out_data, int bytes_in, int* bytes_out);
  void encrypt_rtcp(int channel_no, unsigned char* in_data,
                    unsigned char* out_data, int bytes_in, int* bytes_out);
  void decrypt_rtcp(int channel_no, unsigned char* in_data,
                    unsigned char* out_data, int bytes_in, int* bytes_out);
};

void BasicBitInverseEncryption::encrypt(int, unsigned char* in_data,
                                        unsigned char* out_data,
                                        int bytes_in, int* bytes_out) {
  int i;
  for (i = 0; i < bytes_in; i++)
    out_data[i] = ~in_data[i];
  out_data[bytes_in] = 0;
  out_data[bytes_in + 1] = 0;
  *bytes_out = bytes_in + 2;
}

void BasicBitInverseEncryption::decrypt(int, unsigned char* in_data,
                                        unsigned char* out_data,
                                        int bytes_in, int* bytes_out) {
  int i;
  for (i = 0; i < bytes_in; i++)
    out_data[i] = ~in_data[i];
  *bytes_out = bytes_in - 2;
}

void BasicBitInverseEncryption::encrypt_rtcp(int, unsigned char* in_data,
                                             unsigned char* out_data,
                                             int bytes_in, int* bytes_out) {
  int i;
  for (i = 0; i < bytes_in; i++)
    out_data[i] = ~in_data[i];
  out_data[bytes_in] = 0;
  out_data[bytes_in + 1] = 0;
  *bytes_out = bytes_in + 2;
}

void BasicBitInverseEncryption::decrypt_rtcp(int, unsigned char* in_data,
                                             unsigned char* out_data,
                                             int bytes_in, int* bytes_out) {
  int i;
  for (i = 0; i < bytes_in; i++)
    out_data[i] = ~in_data[i];
  out_data[bytes_in] = 0;
  out_data[bytes_in + 1] = 0;
  *bytes_out = bytes_in + 2;
}

class EncryptionTest : public AfterStreamingFixture {
};

TEST_F(EncryptionTest, ManualBasicCorrectExternalEncryptionHasNoEffectOnVoice) {
  BasicBitInverseEncryption basic_encryption;

  voe_encrypt_->RegisterExternalEncryption(channel_, basic_encryption);

  TEST_LOG("Registered external encryption, should still hear good audio.\n");
  Sleep(3000);

  voe_encrypt_->DeRegisterExternalEncryption(channel_);
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2016 Mick van Duijn, Koen Visscher and Paul Visscher
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "helper.h"

#include <algorithm>

template< typename tBarrier >
void TestBarrierImpl( tBarrier &barrier, bool *check, const std::atomic_bool &abort, size_t id )
{
    barrier.Wait( abort );
    check[id] = true;
    barrier.Wait( abort );
}

template< typename tBarrier >
void TestBarrier( uint32_t threads, const std::atomic_bool &abort )
{
    std::vector< std::future< void > > futures;
    bool *check = new bool[threads];
    std::fill_n( check, threads, false );

    tBarrier barrier( threads );

    for ( size_t i = 0; i < threads - 1; ++i )
    {
        futures.emplace_back( std::async( std::launch::async, [&barrier, &check, &threads, &abort, i]()
        {
            try
            {
                TestBarrierImpl< tBarrier >( barrier, check, abort, i );
            }
            catch ( ... )
            {
                // Ignore other threads
            }
        } ) );

        EXPECT_EQ( 0, std::count_if( check, check + threads, []( bool b )
        {
            return b;
        } ) );
    }

    try
    {
        TestBarrierImpl< tBarrier >( barrier, check, abort, threads - 1 );
    }
    catch ( BSPInternal::BspAbort &e )
    {
        // Make sure all threads are joined, even when an exeption is thrown (mimic the behaviour of Init after Abort)
        for ( auto &thread : futures )
        {
            thread.wait_for( std::chrono::milliseconds( 200 ) );
        }

        throw e;
    }

    EXPECT_EQ( threads, std::count_if( check, check + threads, []( bool b )
    {
        return b;
    } ) );

    // Make sure all threads are joined
    for ( auto &thread : futures )
    {
        thread.wait_for( std::chrono::milliseconds( 200 ) );
    }

    delete check;
}

/*
///  Disabled since spinbarriers are not very cpu friendly
TEST( P( Barrier ), Simple2 )
{
    TestBarrier< BSPInternal::Barrier >( 2, false );
}

TEST( P( Barrier ), Simple4 )
{
    TestBarrier< BSPInternal::Barrier >( 4, false );
}

TEST( P( Barrier ), Simple8 )
{
    TestBarrier< BSPInternal::Barrier >( 8, false );
}

TEST( P( Barrier ), Simple16 )
{
    TestBarrier< BSPInternal::Barrier >( 16, false );
}

TEST( P( Barrier ), Simple32 )
{
    TestBarrier< BSPInternal::Barrier >( 32, false );
}*/

#ifndef DEBUG
TEST( P( CondVarBarrier ), Simple )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 1, std::atomic_bool( false ) );
}

TEST( P( CondVarBarrier ), Simple2 )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 2, std::atomic_bool( false ) );
}

TEST( P( CondVarBarrier ), Simple4 )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 4, std::atomic_bool( false ) );
}

TEST( P( CondVarBarrier ), Simple8 )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 8, std::atomic_bool( false ) );
}

TEST( P( CondVarBarrier ), Simple16 )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 16, std::atomic_bool( false ) );
}

TEST( P( CondVarBarrier ), Simple32 )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 32, std::atomic_bool( false ) );
}

TEST( P( MixedBarrier ), Simple2 )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 2, std::atomic_bool( false ) );
}

TEST( P( MixedBarrier ), Simple4 )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 4, std::atomic_bool( false ) );
}

TEST( P( MixedBarrier ), Simple8 )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 8, std::atomic_bool( false ) );
}

TEST( P( MixedBarrier ), Simple16 )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 16, std::atomic_bool( false ) );
}

TEST( P( MixedBarrier ), Simple32 )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 32, std::atomic_bool( false ) );
}

TEST( P( CondVarBarrier ), Abort2 )
{
    ASSERT_THROW( TestBarrier< BSPInternal::CondVarBarrier >( 2, std::atomic_bool( true ) ), BSPInternal::BspAbort );
}

TEST( P( CondVarBarrier ), Abort4 )
{
    ASSERT_THROW( TestBarrier< BSPInternal::CondVarBarrier >( 4, std::atomic_bool( true ) ), BSPInternal::BspAbort );
}

TEST( P( CondVarBarrier ), Abort8 )
{
    ASSERT_THROW( TestBarrier< BSPInternal::CondVarBarrier >( 8, std::atomic_bool( true ) ), BSPInternal::BspAbort );
}

TEST( P( CondVarBarrier ), Abort16 )
{
    ASSERT_THROW( TestBarrier< BSPInternal::CondVarBarrier >( 16, std::atomic_bool( true ) ), BSPInternal::BspAbort );
}

TEST( P( CondVarBarrier ), Abort32 )
{
    ASSERT_THROW( TestBarrier< BSPInternal::CondVarBarrier >( 32, std::atomic_bool( true ) ), BSPInternal::BspAbort );
}

TEST( P( MixedBarrier ), Abort2 )
{
    ASSERT_THROW( TestBarrier< BSPInternal::MixedBarrier >( 2, std::atomic_bool( true ) ), BSPInternal::BspAbort );
}

TEST( P( MixedBarrier ), Abort4 )
{
    ASSERT_THROW( TestBarrier< BSPInternal::MixedBarrier >( 4, std::atomic_bool( true ) ), BSPInternal::BspAbort );
}

TEST( P( MixedBarrier ), Abort8 )
{
    ASSERT_THROW( TestBarrier< BSPInternal::MixedBarrier >( 8, std::atomic_bool( true ) ), BSPInternal::BspAbort );
}

TEST( P( MixedBarrier ), Abort16 )
{
    ASSERT_THROW( TestBarrier< BSPInternal::MixedBarrier >( 16, std::atomic_bool( true ) ), BSPInternal::BspAbort );
}

TEST( P( MixedBarrier ), Abort32 )
{
    ASSERT_THROW( TestBarrier< BSPInternal::MixedBarrier >( 32, std::atomic_bool( true ) ), BSPInternal::BspAbort );
}

#endif // !DEBUG<commit_msg>Barrier check correct delete<commit_after>/**
 * Copyright (c) 2016 Mick van Duijn, Koen Visscher and Paul Visscher
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "helper.h"

#include <algorithm>

template< typename tBarrier >
void TestBarrierImpl( tBarrier &barrier, bool *check, const std::atomic_bool &abort, size_t id )
{
    barrier.Wait( abort );
    check[id] = true;
    barrier.Wait( abort );
}

template< typename tBarrier >
void TestBarrier( uint32_t threads, const std::atomic_bool &abort )
{
    std::vector< std::future< void > > futures;
    bool *check = new bool[threads];
    std::fill_n( check, threads, false );

    tBarrier barrier( threads );

    for ( size_t i = 0; i < threads - 1; ++i )
    {
        futures.emplace_back( std::async( std::launch::async, [&barrier, &check, &threads, &abort, i]()
        {
            try
            {
                TestBarrierImpl< tBarrier >( barrier, check, abort, i );
            }
            catch ( ... )
            {
                // Ignore other threads
            }
        } ) );

        EXPECT_EQ( 0, std::count_if( check, check + threads, []( bool b )
        {
            return b;
        } ) );
    }

    try
    {
        TestBarrierImpl< tBarrier >( barrier, check, abort, threads - 1 );
    }
    catch ( BSPInternal::BspAbort &e )
    {
        // Make sure all threads are joined, even when an exeption is thrown (mimic the behaviour of Init after Abort)
        for ( auto &thread : futures )
        {
            thread.wait_for( std::chrono::milliseconds( 200 ) );
        }

        throw e;
    }

    EXPECT_EQ( threads, std::count_if( check, check + threads, []( bool b )
    {
        return b;
    } ) );

    // Make sure all threads are joined
    for ( auto &thread : futures )
    {
        thread.wait_for( std::chrono::milliseconds( 200 ) );
    }

    delete[] check;
}

/*
///  Disabled since spinbarriers are not very cpu friendly
TEST( P( Barrier ), Simple2 )
{
    TestBarrier< BSPInternal::Barrier >( 2, false );
}

TEST( P( Barrier ), Simple4 )
{
    TestBarrier< BSPInternal::Barrier >( 4, false );
}

TEST( P( Barrier ), Simple8 )
{
    TestBarrier< BSPInternal::Barrier >( 8, false );
}

TEST( P( Barrier ), Simple16 )
{
    TestBarrier< BSPInternal::Barrier >( 16, false );
}

TEST( P( Barrier ), Simple32 )
{
    TestBarrier< BSPInternal::Barrier >( 32, false );
}*/

#ifndef DEBUG
TEST( P( CondVarBarrier ), Simple )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 1, std::atomic_bool( false ) );
}

TEST( P( CondVarBarrier ), Simple2 )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 2, std::atomic_bool( false ) );
}

TEST( P( CondVarBarrier ), Simple4 )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 4, std::atomic_bool( false ) );
}

TEST( P( CondVarBarrier ), Simple8 )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 8, std::atomic_bool( false ) );
}

TEST( P( CondVarBarrier ), Simple16 )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 16, std::atomic_bool( false ) );
}

TEST( P( CondVarBarrier ), Simple32 )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 32, std::atomic_bool( false ) );
}

TEST( P( MixedBarrier ), Simple2 )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 2, std::atomic_bool( false ) );
}

TEST( P( MixedBarrier ), Simple4 )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 4, std::atomic_bool( false ) );
}

TEST( P( MixedBarrier ), Simple8 )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 8, std::atomic_bool( false ) );
}

TEST( P( MixedBarrier ), Simple16 )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 16, std::atomic_bool( false ) );
}

TEST( P( MixedBarrier ), Simple32 )
{
    TestBarrier< BSPInternal::CondVarBarrier >( 32, std::atomic_bool( false ) );
}

TEST( P( CondVarBarrier ), Abort2 )
{
    ASSERT_THROW( TestBarrier< BSPInternal::CondVarBarrier >( 2, std::atomic_bool( true ) ), BSPInternal::BspAbort );
}

TEST( P( CondVarBarrier ), Abort4 )
{
    ASSERT_THROW( TestBarrier< BSPInternal::CondVarBarrier >( 4, std::atomic_bool( true ) ), BSPInternal::BspAbort );
}

TEST( P( CondVarBarrier ), Abort8 )
{
    ASSERT_THROW( TestBarrier< BSPInternal::CondVarBarrier >( 8, std::atomic_bool( true ) ), BSPInternal::BspAbort );
}

TEST( P( CondVarBarrier ), Abort16 )
{
    ASSERT_THROW( TestBarrier< BSPInternal::CondVarBarrier >( 16, std::atomic_bool( true ) ), BSPInternal::BspAbort );
}

TEST( P( CondVarBarrier ), Abort32 )
{
    ASSERT_THROW( TestBarrier< BSPInternal::CondVarBarrier >( 32, std::atomic_bool( true ) ), BSPInternal::BspAbort );
}

TEST( P( MixedBarrier ), Abort2 )
{
    ASSERT_THROW( TestBarrier< BSPInternal::MixedBarrier >( 2, std::atomic_bool( true ) ), BSPInternal::BspAbort );
}

TEST( P( MixedBarrier ), Abort4 )
{
    ASSERT_THROW( TestBarrier< BSPInternal::MixedBarrier >( 4, std::atomic_bool( true ) ), BSPInternal::BspAbort );
}

TEST( P( MixedBarrier ), Abort8 )
{
    ASSERT_THROW( TestBarrier< BSPInternal::MixedBarrier >( 8, std::atomic_bool( true ) ), BSPInternal::BspAbort );
}

TEST( P( MixedBarrier ), Abort16 )
{
    ASSERT_THROW( TestBarrier< BSPInternal::MixedBarrier >( 16, std::atomic_bool( true ) ), BSPInternal::BspAbort );
}

TEST( P( MixedBarrier ), Abort32 )
{
    ASSERT_THROW( TestBarrier< BSPInternal::MixedBarrier >( 32, std::atomic_bool( true ) ), BSPInternal::BspAbort );
}

#endif // !DEBUG<|endoftext|>


<commit_before>#include <string>
#include <fstream>
#include <iterator>
#include <vector>
#include <algorithm>
#include <af/dim4.hpp>

typedef unsigned char uchar;

template<typename inType, typename outType, typename FileElementType>
void readTests(const std::string &FileName, std::vector<af::dim4> &inputDims,
                std::vector<std::vector<inType>>  &testInputs,
                std::vector<std::vector<outType>> &testOutputs)
{
    using std::vector;

    std::ifstream testFile(FileName);
    if(testFile.good()) {
        unsigned inputCount;
        testFile >> inputCount;
        for(unsigned i=0; i<inputCount; i++) {
            af::dim4 temp(1);
            testFile >> temp;
            inputDims.push_back(temp);
        }

        unsigned testCount;
        testFile >> testCount;
        testOutputs.resize(testCount);

        vector<unsigned> testSizes(testCount);
        for(unsigned i = 0; i < testCount; i++) {
            testFile >> testSizes[i];
        }

        testInputs.resize(inputCount,vector<inType>(0));
        for(unsigned k=0; k<inputCount; k++) {
            unsigned nElems = inputDims[k].elements();
            testInputs[k].resize(nElems);
            FileElementType tmp;
            for(unsigned i = 0; i < nElems; i++) {
                testFile >> tmp;
                testInputs[k][i] = tmp;
            }
        }

        testOutputs.resize(testCount, vector<outType>(0));
        for(unsigned i = 0; i < testCount; i++) {
            testOutputs[i].resize(testSizes[i]);
            FileElementType tmp;
            for(unsigned j = 0; j < testSizes[i]; j++) {
                testFile >> tmp;
                testOutputs[i][j] = tmp;
            }
        }

    }
    else {
        FAIL() << "TEST FILE NOT FOUND";
    }
}
<commit_msg>Added readImageTests and compareArraysRMSD helpers for unit tests<commit_after>#include <string>
#include <fstream>
#include <iterator>
#include <vector>
#include <algorithm>
#include <af/dim4.hpp>
#include <limits>

typedef unsigned char uchar;

template<typename inType, typename outType, typename FileElementType>
void readTests(const std::string &FileName, std::vector<af::dim4> &inputDims,
                std::vector<std::vector<inType>>  &testInputs,
                std::vector<std::vector<outType>> &testOutputs)
{
    using std::vector;

    std::ifstream testFile(FileName);
    if(testFile.good()) {
        unsigned inputCount;
        testFile >> inputCount;
        for(unsigned i=0; i<inputCount; i++) {
            af::dim4 temp(1);
            testFile >> temp;
            inputDims.push_back(temp);
        }

        unsigned testCount;
        testFile >> testCount;
        testOutputs.resize(testCount);

        vector<unsigned> testSizes(testCount);
        for(unsigned i = 0; i < testCount; i++) {
            testFile >> testSizes[i];
        }

        testInputs.resize(inputCount,vector<inType>(0));
        for(unsigned k=0; k<inputCount; k++) {
            unsigned nElems = inputDims[k].elements();
            testInputs[k].resize(nElems);
            FileElementType tmp;
            for(unsigned i = 0; i < nElems; i++) {
                testFile >> tmp;
                testInputs[k][i] = tmp;
            }
        }

        testOutputs.resize(testCount, vector<outType>(0));
        for(unsigned i = 0; i < testCount; i++) {
            testOutputs[i].resize(testSizes[i]);
            FileElementType tmp;
            for(unsigned j = 0; j < testSizes[i]; j++) {
                testFile >> tmp;
                testOutputs[i][j] = tmp;
            }
        }

    }
    else {
        FAIL() << "TEST FILE NOT FOUND";
    }
}

void readImageTests(const std::string        &pFileName,
                    std::vector<af::dim4>    &pInputDims,
                    std::vector<std::string> &pTestInputs,
                    std::vector<dim_type>    &pTestOutSizes,
                    std::vector<std::string> &pTestOutputs)
{
    using std::vector;

    std::ifstream testFile(pFileName);
    if(testFile.good()) {
        unsigned inputCount;
        testFile >> inputCount;
        for(unsigned i=0; i<inputCount; i++) {
            af::dim4 temp(1);
            testFile >> temp;
            pInputDims.push_back(temp);
        }

        unsigned testCount;
        testFile >> testCount;
        pTestOutputs.resize(testCount);

        pTestOutSizes.resize(testCount);
        for(unsigned i = 0; i < testCount; i++) {
            testFile >> pTestOutSizes[i];
        }

        pTestInputs.resize(inputCount, "");
        for(unsigned k=0; k<inputCount; k++) {
            std::string temp = "";
            while(std::getline(testFile, temp)) {
                if (temp!="")
                    break;
            }
            if (temp=="")
                throw std::runtime_error("Test file might not be per format, please check.");
            pTestInputs[k] = temp;
        }

        pTestOutputs.resize(testCount, "");
        for(unsigned i = 0; i < testCount; i++) {
            std::string temp = "";
            while(std::getline(testFile, temp)) {
                if (temp!="")
                    break;
            }
            if (temp=="")
                throw std::runtime_error("Test file might not be per format, please check.");
            pTestOutputs[i] = temp;
        }
    }
    else {
        FAIL() << "TEST FILE NOT FOUND";
    }
}

/**
 * Below is not a pair wise comparition method, rather
 * it computes the accumulated error of the computed
 * output and gold output.
 *
 * The cut off is decided based on root mean square
 * deviation from cpu result
 *
 * For images, the maximum possible error will happen if all
 * the observed values are zeros and all the predicted values
 * are 255's. In such case, the value of NRMSD will be 1.0
 * Similarly, we can deduce that 0.0 will be the minimum
 * value of NRMSD. Hence, the range of RMSD is [0,255] for image inputs.
 */
template<typename T>
bool compareArraysRMSD(dim_type data_size, T *gold, T *data, float tolerance)
{
    float accum = 0.0f;
    T minion    = std::numeric_limits<T>::lowest();
    T maxion    = std::numeric_limits<T>::max();
    for(dim_type i=0;i<data_size;i++)
    {
        float diff = fabs(gold[i]-data[i]) > 1.0e-4 ? gold[i]-data[i] : 0.0f;
        accum  += pow(diff,2.0f);
        maxion  = std::max(maxion, data[i]);
        minion  = std::min(minion, data[i]);
    }
    accum      /= data_size;
    float NRMSD = sqrt(accum)/(float)(maxion-minion);

    if (NRMSD > tolerance)
        return false;

    return true;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2018 Dubalu LLC. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "check_size.h"

#ifdef XAPIAND_CHECK_SIZES
#define STATIC_ASSERT(...)
// #define STATIC_ASSERT static_assert
#define CHECK_MAX_SIZE(max_size, name) \
	STATIC_ASSERT((max_size) >= (sizeof name), "Object is too big!"); \
	if ((max_size) < (sizeof name)) { \
		std::cerr << "sizeof" << #name << " = " << (sizeof name) << std::endl; \
	}

#include "allocator.h"
#include "base_x.hh"
#include "bloom_filter.hh"
#include "compressor_deflate.h"
#include "compressor_lz4.h"
#include "database.h"
#include "database_handler.h"
#include "database_pool.h"
#include "database_wal.h"
#include "debouncer.h"
#include "endpoint.h"
#include "logger.h"
#include "manager.h"
#include "msgpack.h"
#include "node.h"
#include "query_dsl.h"
#include "queue.h"
#include "schema.h"
#include "schemas_lru.h"
#include "script.h"
#include "storage.h"
#include "threadpool.hh"
#include "url_parser.h"
#include "url_parser.h"
#include "booleanParser/BooleanParser.h"
#include "chaipp/chaipp.h"
#include "cuuid/uuid.h"
#include "geospatial/geometry.h"
#include "geospatial/geospatial.h"
#include "geospatial/intersection.h"
#include "geospatial/multicircle.h"
#include "geospatial/multiconvex.h"
#include "geospatial/multipoint.h"
#include "geospatial/multipolygon.h"
#include "geospatial/point.h"
#include "geospatial/polygon.h"
#include "metrics/basic_string_metric.h"
#include "metrics/jaccard.h"
#include "metrics/jaro.h"
#include "metrics/jaro_winkler.h"
#include "metrics/lcsubsequence.h"
#include "metrics/lcsubstr.h"
#include "metrics/levenshtein.h"
#include "metrics/sorensen_dice.h"
#include "metrics/soundex_metric.h"
#include "multivalue/aggregation.h"
#include "multivalue/aggregation_bucket.h"
#include "multivalue/aggregation_metric.h"
#include "multivalue/geospatialrange.h"
#include "multivalue/keymaker.h"
#include "multivalue/range.h"
#include "phonetic/english_soundex.h"
#include "phonetic/french_soundex.h"
#include "phonetic/german_soundex.h"
#include "phonetic/spanish_soundex.h"
#include "server/base_client.h"
#include "server/binary.h"
#include "server/binary_client.h"
#include "server/binary_server.h"
#include "server/buffer.h"
#include "server/discovery.h"
#include "server/http.h"
#include "server/http_client.h"
#include "server/http_server.h"
#include "server/raft.h"
#include "server/remote_protocol.h"
#include "server/replication_protocol.h"
#include "v8pp/v8pp.h"

#define TINY 8
#define SMALL 128
#define REGULAR 1024
#define BIG 5 * 1024
#define LARGE 20 * 1024

class DummyClient {
	ssize_t on_read(const char*, ssize_t) { return 0; }
	void on_read_file(const char*, ssize_t) {}
	void on_read_file_done() {}
};

void
check_size()
{

// allocator.h
CHECK_MAX_SIZE(TINY, (allocator::VanillaAllocator))
CHECK_MAX_SIZE(TINY, (allocator::TrackedAllocator))

// base_x.hh
CHECK_MAX_SIZE(TINY, (BaseX))
CHECK_MAX_SIZE(TINY, (Base2))
CHECK_MAX_SIZE(TINY, (Base8))
CHECK_MAX_SIZE(TINY, (Base11))
CHECK_MAX_SIZE(TINY, (Base16))
CHECK_MAX_SIZE(TINY, (Base32))
CHECK_MAX_SIZE(TINY, (Base36))
CHECK_MAX_SIZE(TINY, (Base58))
CHECK_MAX_SIZE(TINY, (Base59))
CHECK_MAX_SIZE(TINY, (Base62))
CHECK_MAX_SIZE(TINY, (Base64))
CHECK_MAX_SIZE(TINY, (Base66))

// bloom_filter.hh
CHECK_MAX_SIZE(SMALL, (BloomFilter<>))

// compressor_deflate.h
CHECK_MAX_SIZE(SMALL, (DeflateCompressData))
CHECK_MAX_SIZE(SMALL, (DeflateCompressFile))
CHECK_MAX_SIZE(SMALL, (DeflateDecompressData))
CHECK_MAX_SIZE(SMALL, (DeflateDecompressFile))

// compressor_lz4.h
CHECK_MAX_SIZE(SMALL, (LZ4CompressData))
CHECK_MAX_SIZE(SMALL, (LZ4CompressFile))
CHECK_MAX_SIZE(SMALL, (LZ4DecompressData))
CHECK_MAX_SIZE(SMALL, (LZ4DecompressFile))

// database.h
CHECK_MAX_SIZE(SMALL, (Database))

// database_handler.h
CHECK_MAX_SIZE(SMALL, (Data))
CHECK_MAX_SIZE(SMALL, (DatabaseHandler))
CHECK_MAX_SIZE(SMALL, (Document))
CHECK_MAX_SIZE(SMALL, (MSet))

// database_pool.h
CHECK_MAX_SIZE(SMALL, (DatabaseCount))
CHECK_MAX_SIZE(SMALL, (DatabaseQueue))
CHECK_MAX_SIZE(SMALL, (DatabasesLRU))
CHECK_MAX_SIZE(SMALL, (DatabasePool))

// database_wal.h
CHECK_MAX_SIZE(BIG, (WalHeader))
CHECK_MAX_SIZE(TINY, (WalBinHeader))
CHECK_MAX_SIZE(TINY, (WalBinFooter))
CHECK_MAX_SIZE(SMALL, (DatabaseWAL))

// debouncer.h
// CHECK_MAX_SIZE(SMALL, (Debouncer<int, 0, 0, 0, void(*)(), int>))

// endpoint.h
CHECK_MAX_SIZE(SMALL, (Endpoint))
CHECK_MAX_SIZE(SMALL, (Endpoints))

// logger.h
CHECK_MAX_SIZE(SMALL, (Logging))

// manager.h
CHECK_MAX_SIZE(SMALL, (XapiandManager))

// msgpack.h
CHECK_MAX_SIZE(SMALL, (MsgPack))

// node.h
CHECK_MAX_SIZE(SMALL, (Node))

// query_dsl.h
CHECK_MAX_SIZE(SMALL, (QueryDSL))

// queue.h
CHECK_MAX_SIZE(SMALL, (queue::Queue<int>))

// remote_protocol.h
CHECK_MAX_SIZE(SMALL, (RemoteProtocol))

// replication.h
CHECK_MAX_SIZE(SMALL, (Replication))

// schema.h
CHECK_MAX_SIZE(SMALL, (Schema))

// schemas_lru.h
CHECK_MAX_SIZE(SMALL, (SchemasLRU))

// script.h
CHECK_MAX_SIZE(SMALL, (Script))

// storage.h
CHECK_MAX_SIZE(SMALL, (Storage<StorageHeader, StorageBinHeader, StorageBinFooter>))

// threadpool.hh
CHECK_MAX_SIZE(SMALL, (ThreadPool<>))

// url_parser.h
CHECK_MAX_SIZE(SMALL, (QueryParser))
CHECK_MAX_SIZE(SMALL, (PathParser))

// booleanParser/BooleanParser.h
CHECK_MAX_SIZE(SMALL, (BooleanTree))

// cuuid/uuid.h
CHECK_MAX_SIZE(SMALL, (UUID))

// geospatial/geometry.h
CHECK_MAX_SIZE(SMALL, (Constraint))
CHECK_MAX_SIZE(SMALL, (Geometry))
// geospatial/geospatial.h
CHECK_MAX_SIZE(SMALL, (GeoSpatial))
// geospatial/intersection.h
CHECK_MAX_SIZE(SMALL, (Intersection))
// geospatial/multicircle.h
CHECK_MAX_SIZE(SMALL, (MultiCircle))
// geospatial/multiconvex.h
CHECK_MAX_SIZE(SMALL, (MultiConvex))
// geospatial/multipoint.h
CHECK_MAX_SIZE(SMALL, (MultiPoint))
// geospatial/multipolygon.h
CHECK_MAX_SIZE(SMALL, (MultiPolygon))
// geospatial/point.h
CHECK_MAX_SIZE(SMALL, (Point))
// geospatial/polygon.h
CHECK_MAX_SIZE(SMALL, (Polygon))

// metrics/basic_string_metric.h
CHECK_MAX_SIZE(SMALL, (Counter))
// metrics/jaccard.h
CHECK_MAX_SIZE(SMALL, (Jaccard))
// metrics/jaro.h
CHECK_MAX_SIZE(SMALL, (Jaro))
// metrics/jaro_winkler.h
CHECK_MAX_SIZE(SMALL, (Jaro_Winkler))
// metrics/lcsubsequence.h
CHECK_MAX_SIZE(SMALL, (LCSubsequence))
// metrics/lcsubstr.h
CHECK_MAX_SIZE(SMALL, (LCSubstr))
// metrics/levenshtein.h
CHECK_MAX_SIZE(SMALL, (Levenshtein))
// metrics/sorensen_dice.h
CHECK_MAX_SIZE(SMALL, (Sorensen_Dice))
// metrics/soundex_metric.h
// CHECK_MAX_SIZE(SMALL, (SoundexMetric))

// multivalue/aggregation.h
CHECK_MAX_SIZE(SMALL, (Aggregation))
CHECK_MAX_SIZE(SMALL, (AggregationMatchSpy))

// multivalue/aggregation_bucket.h
CHECK_MAX_SIZE(SMALL, (BucketAggregation))
CHECK_MAX_SIZE(SMALL, (ValueAggregation))
CHECK_MAX_SIZE(SMALL, (HistogramAggregation))
CHECK_MAX_SIZE(SMALL, (RangeAggregation))
CHECK_MAX_SIZE(SMALL, (FilterAggregation))

// multivalue/aggregation_metric.h
CHECK_MAX_SIZE(SMALL, (ValueHandle))
CHECK_MAX_SIZE(SMALL, (SubAggregation))
CHECK_MAX_SIZE(SMALL, (HandledSubAggregation))
CHECK_MAX_SIZE(SMALL, (MetricCount))
CHECK_MAX_SIZE(SMALL, (MetricSum))
CHECK_MAX_SIZE(SMALL, (MetricAvg))
CHECK_MAX_SIZE(SMALL, (MetricMin))
CHECK_MAX_SIZE(SMALL, (MetricMax))
CHECK_MAX_SIZE(SMALL, (MetricVariance))
CHECK_MAX_SIZE(SMALL, (MetricSTD))
CHECK_MAX_SIZE(SMALL, (MetricMedian))
CHECK_MAX_SIZE(SMALL, (MetricMode))
CHECK_MAX_SIZE(SMALL, (MetricStats))
CHECK_MAX_SIZE(SMALL, (MetricExtendedStats))

// multivalue/geospatialrange.h
CHECK_MAX_SIZE(SMALL, (GeoSpatialRange))

// multivalue/keymaker.h
CHECK_MAX_SIZE(SMALL, (Multi_MultiValueKeyMaker))

// multivalue/range.h
CHECK_MAX_SIZE(SMALL, (MultipleValueRange))
CHECK_MAX_SIZE(SMALL, (MultipleValueGE))
CHECK_MAX_SIZE(SMALL, (MultipleValueLE))

// phonetic
CHECK_MAX_SIZE(SMALL, (SoundexEnglish))
CHECK_MAX_SIZE(SMALL, (SoundexFrench))
CHECK_MAX_SIZE(SMALL, (SoundexGerman))
CHECK_MAX_SIZE(SMALL, (SoundexSpanish))

// server/base_client.h
CHECK_MAX_SIZE(SMALL, (MetaBaseClient<DummyClient>))

// server/buffer.h
CHECK_MAX_SIZE(SMALL, (Buffer))

// server/http.h
CHECK_MAX_SIZE(SMALL, (Http))

// server/http_server.h
CHECK_MAX_SIZE(SMALL, (HttpServer))

// server/http_client.h
CHECK_MAX_SIZE(SMALL, (HttpClient))
CHECK_MAX_SIZE(SMALL, (Response))
CHECK_MAX_SIZE(SMALL, (Request))

// server/binary.h
CHECK_MAX_SIZE(SMALL, (Binary))

// server/binary_server.h
CHECK_MAX_SIZE(SMALL, (BinaryServer))

// server/binary_client.h
CHECK_MAX_SIZE(SMALL, (BinaryClient))

// server/raft.h
CHECK_MAX_SIZE(SMALL, (Raft))

// server/discovery.h
CHECK_MAX_SIZE(SMALL, (Discovery))

#if XAPIAND_CHAISCRIPT
// chaipp/chaipp.h
CHECK_MAX_SIZE(SMALL, (chaipp::Processor))
#endif

#if XAPIAND_V8
// v8pp/v8pp.h
CHECK_MAX_SIZE(SMALL, (v8pp::Processor))
#endif

}

#endif
<commit_msg>Check Size: Removed DatabaseCount, DatabaseQueue and DatabasesLRU<commit_after>/*
 * Copyright (C) 2018 Dubalu LLC. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "check_size.h"

#ifdef XAPIAND_CHECK_SIZES
#define STATIC_ASSERT(...)
// #define STATIC_ASSERT static_assert
#define CHECK_MAX_SIZE(max_size, name) \
	STATIC_ASSERT((max_size) >= (sizeof name), "Object is too big!"); \
	if ((max_size) < (sizeof name)) { \
		std::cerr << "sizeof" << #name << " = " << (sizeof name) << std::endl; \
	}

#include "allocator.h"
#include "base_x.hh"
#include "bloom_filter.hh"
#include "compressor_deflate.h"
#include "compressor_lz4.h"
#include "database.h"
#include "database_handler.h"
#include "database_pool.h"
#include "database_wal.h"
#include "debouncer.h"
#include "endpoint.h"
#include "logger.h"
#include "manager.h"
#include "msgpack.h"
#include "node.h"
#include "query_dsl.h"
#include "queue.h"
#include "schema.h"
#include "schemas_lru.h"
#include "script.h"
#include "storage.h"
#include "threadpool.hh"
#include "url_parser.h"
#include "url_parser.h"
#include "booleanParser/BooleanParser.h"
#include "chaipp/chaipp.h"
#include "cuuid/uuid.h"
#include "geospatial/geometry.h"
#include "geospatial/geospatial.h"
#include "geospatial/intersection.h"
#include "geospatial/multicircle.h"
#include "geospatial/multiconvex.h"
#include "geospatial/multipoint.h"
#include "geospatial/multipolygon.h"
#include "geospatial/point.h"
#include "geospatial/polygon.h"
#include "metrics/basic_string_metric.h"
#include "metrics/jaccard.h"
#include "metrics/jaro.h"
#include "metrics/jaro_winkler.h"
#include "metrics/lcsubsequence.h"
#include "metrics/lcsubstr.h"
#include "metrics/levenshtein.h"
#include "metrics/sorensen_dice.h"
#include "metrics/soundex_metric.h"
#include "multivalue/aggregation.h"
#include "multivalue/aggregation_bucket.h"
#include "multivalue/aggregation_metric.h"
#include "multivalue/geospatialrange.h"
#include "multivalue/keymaker.h"
#include "multivalue/range.h"
#include "phonetic/english_soundex.h"
#include "phonetic/french_soundex.h"
#include "phonetic/german_soundex.h"
#include "phonetic/spanish_soundex.h"
#include "server/base_client.h"
#include "server/binary.h"
#include "server/binary_client.h"
#include "server/binary_server.h"
#include "server/buffer.h"
#include "server/discovery.h"
#include "server/http.h"
#include "server/http_client.h"
#include "server/http_server.h"
#include "server/raft.h"
#include "server/remote_protocol.h"
#include "server/replication_protocol.h"
#include "v8pp/v8pp.h"

#define TINY 8
#define SMALL 128
#define REGULAR 1024
#define BIG 5 * 1024
#define LARGE 20 * 1024

class DummyClient {
	ssize_t on_read(const char*, ssize_t) { return 0; }
	void on_read_file(const char*, ssize_t) {}
	void on_read_file_done() {}
};

void
check_size()
{

// allocator.h
CHECK_MAX_SIZE(TINY, (allocator::VanillaAllocator))
CHECK_MAX_SIZE(TINY, (allocator::TrackedAllocator))

// base_x.hh
CHECK_MAX_SIZE(TINY, (BaseX))
CHECK_MAX_SIZE(TINY, (Base2))
CHECK_MAX_SIZE(TINY, (Base8))
CHECK_MAX_SIZE(TINY, (Base11))
CHECK_MAX_SIZE(TINY, (Base16))
CHECK_MAX_SIZE(TINY, (Base32))
CHECK_MAX_SIZE(TINY, (Base36))
CHECK_MAX_SIZE(TINY, (Base58))
CHECK_MAX_SIZE(TINY, (Base59))
CHECK_MAX_SIZE(TINY, (Base62))
CHECK_MAX_SIZE(TINY, (Base64))
CHECK_MAX_SIZE(TINY, (Base66))

// bloom_filter.hh
CHECK_MAX_SIZE(SMALL, (BloomFilter<>))

// compressor_deflate.h
CHECK_MAX_SIZE(SMALL, (DeflateCompressData))
CHECK_MAX_SIZE(SMALL, (DeflateCompressFile))
CHECK_MAX_SIZE(SMALL, (DeflateDecompressData))
CHECK_MAX_SIZE(SMALL, (DeflateDecompressFile))

// compressor_lz4.h
CHECK_MAX_SIZE(SMALL, (LZ4CompressData))
CHECK_MAX_SIZE(SMALL, (LZ4CompressFile))
CHECK_MAX_SIZE(SMALL, (LZ4DecompressData))
CHECK_MAX_SIZE(SMALL, (LZ4DecompressFile))

// database.h
CHECK_MAX_SIZE(SMALL, (Database))

// database_handler.h
CHECK_MAX_SIZE(SMALL, (Data))
CHECK_MAX_SIZE(SMALL, (DatabaseHandler))
CHECK_MAX_SIZE(SMALL, (Document))
CHECK_MAX_SIZE(SMALL, (MSet))

// database_pool.h
CHECK_MAX_SIZE(SMALL, (DatabaseEndpoint))
CHECK_MAX_SIZE(SMALL, (DatabasePool))

// database_wal.h
CHECK_MAX_SIZE(BIG, (WalHeader))
CHECK_MAX_SIZE(TINY, (WalBinHeader))
CHECK_MAX_SIZE(TINY, (WalBinFooter))
CHECK_MAX_SIZE(SMALL, (DatabaseWAL))

// debouncer.h
// CHECK_MAX_SIZE(SMALL, (Debouncer<int, 0, 0, 0, void(*)(), int>))

// endpoint.h
CHECK_MAX_SIZE(SMALL, (Endpoint))
CHECK_MAX_SIZE(SMALL, (Endpoints))

// logger.h
CHECK_MAX_SIZE(SMALL, (Logging))

// manager.h
CHECK_MAX_SIZE(SMALL, (XapiandManager))

// msgpack.h
CHECK_MAX_SIZE(SMALL, (MsgPack))

// node.h
CHECK_MAX_SIZE(SMALL, (Node))

// query_dsl.h
CHECK_MAX_SIZE(SMALL, (QueryDSL))

// queue.h
CHECK_MAX_SIZE(SMALL, (queue::Queue<int>))

// remote_protocol.h
CHECK_MAX_SIZE(SMALL, (RemoteProtocol))

// replication.h
CHECK_MAX_SIZE(SMALL, (Replication))

// schema.h
CHECK_MAX_SIZE(SMALL, (Schema))

// schemas_lru.h
CHECK_MAX_SIZE(SMALL, (SchemasLRU))

// script.h
CHECK_MAX_SIZE(SMALL, (Script))

// storage.h
CHECK_MAX_SIZE(SMALL, (Storage<StorageHeader, StorageBinHeader, StorageBinFooter>))

// threadpool.hh
CHECK_MAX_SIZE(SMALL, (ThreadPool<>))

// url_parser.h
CHECK_MAX_SIZE(SMALL, (QueryParser))
CHECK_MAX_SIZE(SMALL, (PathParser))

// booleanParser/BooleanParser.h
CHECK_MAX_SIZE(SMALL, (BooleanTree))

// cuuid/uuid.h
CHECK_MAX_SIZE(SMALL, (UUID))

// geospatial/geometry.h
CHECK_MAX_SIZE(SMALL, (Constraint))
CHECK_MAX_SIZE(SMALL, (Geometry))
// geospatial/geospatial.h
CHECK_MAX_SIZE(SMALL, (GeoSpatial))
// geospatial/intersection.h
CHECK_MAX_SIZE(SMALL, (Intersection))
// geospatial/multicircle.h
CHECK_MAX_SIZE(SMALL, (MultiCircle))
// geospatial/multiconvex.h
CHECK_MAX_SIZE(SMALL, (MultiConvex))
// geospatial/multipoint.h
CHECK_MAX_SIZE(SMALL, (MultiPoint))
// geospatial/multipolygon.h
CHECK_MAX_SIZE(SMALL, (MultiPolygon))
// geospatial/point.h
CHECK_MAX_SIZE(SMALL, (Point))
// geospatial/polygon.h
CHECK_MAX_SIZE(SMALL, (Polygon))

// metrics/basic_string_metric.h
CHECK_MAX_SIZE(SMALL, (Counter))
// metrics/jaccard.h
CHECK_MAX_SIZE(SMALL, (Jaccard))
// metrics/jaro.h
CHECK_MAX_SIZE(SMALL, (Jaro))
// metrics/jaro_winkler.h
CHECK_MAX_SIZE(SMALL, (Jaro_Winkler))
// metrics/lcsubsequence.h
CHECK_MAX_SIZE(SMALL, (LCSubsequence))
// metrics/lcsubstr.h
CHECK_MAX_SIZE(SMALL, (LCSubstr))
// metrics/levenshtein.h
CHECK_MAX_SIZE(SMALL, (Levenshtein))
// metrics/sorensen_dice.h
CHECK_MAX_SIZE(SMALL, (Sorensen_Dice))
// metrics/soundex_metric.h
// CHECK_MAX_SIZE(SMALL, (SoundexMetric))

// multivalue/aggregation.h
CHECK_MAX_SIZE(SMALL, (Aggregation))
CHECK_MAX_SIZE(SMALL, (AggregationMatchSpy))

// multivalue/aggregation_bucket.h
CHECK_MAX_SIZE(SMALL, (BucketAggregation))
CHECK_MAX_SIZE(SMALL, (ValueAggregation))
CHECK_MAX_SIZE(SMALL, (HistogramAggregation))
CHECK_MAX_SIZE(SMALL, (RangeAggregation))
CHECK_MAX_SIZE(SMALL, (FilterAggregation))

// multivalue/aggregation_metric.h
CHECK_MAX_SIZE(SMALL, (ValueHandle))
CHECK_MAX_SIZE(SMALL, (SubAggregation))
CHECK_MAX_SIZE(SMALL, (HandledSubAggregation))
CHECK_MAX_SIZE(SMALL, (MetricCount))
CHECK_MAX_SIZE(SMALL, (MetricSum))
CHECK_MAX_SIZE(SMALL, (MetricAvg))
CHECK_MAX_SIZE(SMALL, (MetricMin))
CHECK_MAX_SIZE(SMALL, (MetricMax))
CHECK_MAX_SIZE(SMALL, (MetricVariance))
CHECK_MAX_SIZE(SMALL, (MetricSTD))
CHECK_MAX_SIZE(SMALL, (MetricMedian))
CHECK_MAX_SIZE(SMALL, (MetricMode))
CHECK_MAX_SIZE(SMALL, (MetricStats))
CHECK_MAX_SIZE(SMALL, (MetricExtendedStats))

// multivalue/geospatialrange.h
CHECK_MAX_SIZE(SMALL, (GeoSpatialRange))

// multivalue/keymaker.h
CHECK_MAX_SIZE(SMALL, (Multi_MultiValueKeyMaker))

// multivalue/range.h
CHECK_MAX_SIZE(SMALL, (MultipleValueRange))
CHECK_MAX_SIZE(SMALL, (MultipleValueGE))
CHECK_MAX_SIZE(SMALL, (MultipleValueLE))

// phonetic
CHECK_MAX_SIZE(SMALL, (SoundexEnglish))
CHECK_MAX_SIZE(SMALL, (SoundexFrench))
CHECK_MAX_SIZE(SMALL, (SoundexGerman))
CHECK_MAX_SIZE(SMALL, (SoundexSpanish))

// server/base_client.h
CHECK_MAX_SIZE(SMALL, (MetaBaseClient<DummyClient>))

// server/buffer.h
CHECK_MAX_SIZE(SMALL, (Buffer))

// server/http.h
CHECK_MAX_SIZE(SMALL, (Http))

// server/http_server.h
CHECK_MAX_SIZE(SMALL, (HttpServer))

// server/http_client.h
CHECK_MAX_SIZE(SMALL, (HttpClient))
CHECK_MAX_SIZE(SMALL, (Response))
CHECK_MAX_SIZE(SMALL, (Request))

// server/binary.h
CHECK_MAX_SIZE(SMALL, (Binary))

// server/binary_server.h
CHECK_MAX_SIZE(SMALL, (BinaryServer))

// server/binary_client.h
CHECK_MAX_SIZE(SMALL, (BinaryClient))

// server/raft.h
CHECK_MAX_SIZE(SMALL, (Raft))

// server/discovery.h
CHECK_MAX_SIZE(SMALL, (Discovery))

#if XAPIAND_CHAISCRIPT
// chaipp/chaipp.h
CHECK_MAX_SIZE(SMALL, (chaipp::Processor))
#endif

#if XAPIAND_V8
// v8pp/v8pp.h
CHECK_MAX_SIZE(SMALL, (v8pp::Processor))
#endif

}

#endif
<|endoftext|>


<commit_before>/***************************************************************************
 * Copyright (c) 2009-2010 Open Information Security Foundation
 * Copyright (c) 2010-2013 Qualys, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.

 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.

 * - Neither the name of the Qualys, Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ***************************************************************************/

/**
 * @file
 *
 * @author Ivan Ristic <ivanr@webkreator.com>
 */

#include <iostream>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <gtest/gtest.h>
#include "htp/htp.h"
#include "htp/htp_decompressors.h"

static htp_status_t GUnzip_decompressor_callback(htp_tx_data_t *d) {
    // fprint_raw_data(stdout, "decompressed", d->data, d->len);

    bstr **output = (bstr **)htp_tx_get_user_data(d->tx);
    *output = bstr_dup_mem(d->data, d->len);

    return HTP_OK;
}

class GUnzip : public testing::Test {

protected:

    virtual htp_status_t decompressFile(const char *f) {
        // Construct complete file name

        char filename[1025];
        strncpy(filename, home, 1024);
        strncat(filename, "/", 1024 - strlen(filename));
        strncat(filename, f, 1024 - strlen(filename));

        // Load test data

        int fd = open(filename, O_RDONLY | O_BINARY);
        if (fd < 0) {
            //FAIL() << "Unable to open test file";
            return HTP_ERROR;
        }

        struct stat statbuf;
        if (fstat(fd, &statbuf) < 0) {
            //FAIL() << "Unable to stat test file";
            return HTP_ERROR;
        }

        htp_tx_data_t d;
        d.tx = tx;
        d.len = statbuf.st_size;
        d.data = (const unsigned char *)malloc(d.len);
        if (d.data == NULL) {
            //FAIL() << "Memory allocation failed";
            return HTP_ERROR;
        }

        if (read(fd, (void *)d.data, d.len) != d.len) {
            //FAIL() << "Reading from test file failed";
            close(fd);
            return HTP_ERROR;
        }

        close(fd);

        // Decompress

        return decompressor->decompress(decompressor, &d);
    }

    virtual void SetUp() {
        home = getenv("srcdir");
        if (home == NULL) {
            fprintf(stderr, "This program needs environment variable 'srcdir' set.");
            exit(EXIT_FAILURE);
        }

        cfg = htp_config_create();
        htp_config_set_server_personality(cfg, HTP_SERVER_APACHE_2);

        connp = htp_connp_create(cfg);
        tx = htp_connp_tx_create(connp);
        htp_tx_set_user_data(tx, &output);

        decompressor = htp_gzip_decompressor_create(connp, COMPRESSION_GZIP);
        decompressor->callback = GUnzip_decompressor_callback;

        o_boxing_wizards = bstr_dup_c("The five boxing wizards jump quickly.");
        output = NULL;
    }

    virtual void TearDown() {
        bstr_free(&output);
        bstr_free(&o_boxing_wizards);
        decompressor->destroy(decompressor);
        htp_connp_destroy_all(connp);
        htp_config_destroy(cfg);
    }

    bstr *output;

    bstr *o_boxing_wizards;

    htp_connp_t *connp;

    htp_tx_t *tx;

    htp_cfg_t *cfg;

    char *home;

    htp_decompressor_t *decompressor;
};

TEST_F(GUnzip, Minimal) {
    htp_status_t rc = decompressFile("gztest-01-minimal.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

TEST_F(GUnzip, FNAME) {
    htp_status_t rc = decompressFile("gztest-02-fname.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

#if 0
TEST_F(GUnzip, FCOMMENT) {
    htp_status_t rc = decompressFile("gztest-03-fcomment.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

TEST_F(GUnzip, FHCRC) {
    htp_status_t rc = decompressFile("gztest-04-fhcrc.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}
#endif

TEST_F(GUnzip, FEXTRA) {
    htp_status_t rc = decompressFile("gztest-05-fextra.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

TEST_F(GUnzip, FTEXT) {
    htp_status_t rc = decompressFile("gztest-06-ftext.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

#if 0
TEST_F(GUnzip, FRESERVED1) {
    htp_status_t rc = decompressFile("gztest-07-freserved1.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

TEST_F(GUnzip, FRESERVED2) {
    htp_status_t rc = decompressFile("gztest-08-freserved2.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

TEST_F(GUnzip, FRESERVED3) {
    htp_status_t rc = decompressFile("gztest-09-freserved3.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}
#endif

TEST_F(GUnzip, Multipart) {
    htp_status_t rc = decompressFile("gztest-10-multipart.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

#if 0
TEST_F(GUnzip, InvalidMethod) {
    htp_status_t rc = decompressFile("gztest-11-invalid-method.gz.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

TEST_F(GUnzip, InvalidCrc) {
    htp_status_t rc = decompressFile("gztest-12-invalid-crc32.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

TEST_F(GUnzip, InvalidInputSize) {
    htp_status_t rc = decompressFile("gztest-13-invalid-isize.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}
#endif

TEST_F(GUnzip, InvalidExtraFlags) {
    htp_status_t rc = decompressFile("gztest-14-invalid-xfl.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

TEST_F(GUnzip, InvalidHeaderCrc) {
    htp_status_t rc = decompressFile("gztest-15-invalid-fhcrc.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}
<commit_msg>Ignore O_BINARY on non-Windows platforms.<commit_after>/***************************************************************************
 * Copyright (c) 2009-2010 Open Information Security Foundation
 * Copyright (c) 2010-2013 Qualys, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.

 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.

 * - Neither the name of the Qualys, Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ***************************************************************************/

/**
 * @file
 *
 * @author Ivan Ristic <ivanr@webkreator.com>
 */

#include <iostream>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <gtest/gtest.h>
#include "htp/htp.h"
#include "htp/htp_decompressors.h"

#ifndef O_BINARY
#define O_BINARY 0
#endif

static htp_status_t GUnzip_decompressor_callback(htp_tx_data_t *d) {
    // fprint_raw_data(stdout, "decompressed", d->data, d->len);

    bstr **output = (bstr **)htp_tx_get_user_data(d->tx);
    *output = bstr_dup_mem(d->data, d->len);

    return HTP_OK;
}

class GUnzip : public testing::Test {

protected:

    virtual htp_status_t decompressFile(const char *f) {
        // Construct complete file name

        char filename[1025];
        strncpy(filename, home, 1024);
        strncat(filename, "/", 1024 - strlen(filename));
        strncat(filename, f, 1024 - strlen(filename));

        // Load test data

        int fd = open(filename, O_RDONLY | O_BINARY);
        if (fd < 0) {
            //FAIL() << "Unable to open test file";
            return HTP_ERROR;
        }

        struct stat statbuf;
        if (fstat(fd, &statbuf) < 0) {
            //FAIL() << "Unable to stat test file";
            return HTP_ERROR;
        }

        htp_tx_data_t d;
        d.tx = tx;
        d.len = statbuf.st_size;
        d.data = (const unsigned char *)malloc(d.len);
        if (d.data == NULL) {
            //FAIL() << "Memory allocation failed";
            return HTP_ERROR;
        }

        if (read(fd, (void *)d.data, d.len) != d.len) {
            //FAIL() << "Reading from test file failed";
            close(fd);
            return HTP_ERROR;
        }

        close(fd);

        // Decompress

        return decompressor->decompress(decompressor, &d);
    }

    virtual void SetUp() {
        home = getenv("srcdir");
        if (home == NULL) {
            fprintf(stderr, "This program needs environment variable 'srcdir' set.");
            exit(EXIT_FAILURE);
        }

        cfg = htp_config_create();
        htp_config_set_server_personality(cfg, HTP_SERVER_APACHE_2);

        connp = htp_connp_create(cfg);
        tx = htp_connp_tx_create(connp);
        htp_tx_set_user_data(tx, &output);

        decompressor = htp_gzip_decompressor_create(connp, COMPRESSION_GZIP);
        decompressor->callback = GUnzip_decompressor_callback;

        o_boxing_wizards = bstr_dup_c("The five boxing wizards jump quickly.");
        output = NULL;
    }

    virtual void TearDown() {
        bstr_free(&output);
        bstr_free(&o_boxing_wizards);
        decompressor->destroy(decompressor);
        htp_connp_destroy_all(connp);
        htp_config_destroy(cfg);
    }

    bstr *output;

    bstr *o_boxing_wizards;

    htp_connp_t *connp;

    htp_tx_t *tx;

    htp_cfg_t *cfg;

    char *home;

    htp_decompressor_t *decompressor;
};

TEST_F(GUnzip, Minimal) {
    htp_status_t rc = decompressFile("gztest-01-minimal.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

TEST_F(GUnzip, FNAME) {
    htp_status_t rc = decompressFile("gztest-02-fname.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

#if 0
TEST_F(GUnzip, FCOMMENT) {
    htp_status_t rc = decompressFile("gztest-03-fcomment.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

TEST_F(GUnzip, FHCRC) {
    htp_status_t rc = decompressFile("gztest-04-fhcrc.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}
#endif

TEST_F(GUnzip, FEXTRA) {
    htp_status_t rc = decompressFile("gztest-05-fextra.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

TEST_F(GUnzip, FTEXT) {
    htp_status_t rc = decompressFile("gztest-06-ftext.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

#if 0
TEST_F(GUnzip, FRESERVED1) {
    htp_status_t rc = decompressFile("gztest-07-freserved1.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

TEST_F(GUnzip, FRESERVED2) {
    htp_status_t rc = decompressFile("gztest-08-freserved2.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

TEST_F(GUnzip, FRESERVED3) {
    htp_status_t rc = decompressFile("gztest-09-freserved3.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}
#endif

TEST_F(GUnzip, Multipart) {
    htp_status_t rc = decompressFile("gztest-10-multipart.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

#if 0
TEST_F(GUnzip, InvalidMethod) {
    htp_status_t rc = decompressFile("gztest-11-invalid-method.gz.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

TEST_F(GUnzip, InvalidCrc) {
    htp_status_t rc = decompressFile("gztest-12-invalid-crc32.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

TEST_F(GUnzip, InvalidInputSize) {
    htp_status_t rc = decompressFile("gztest-13-invalid-isize.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}
#endif

TEST_F(GUnzip, InvalidExtraFlags) {
    htp_status_t rc = decompressFile("gztest-14-invalid-xfl.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}

TEST_F(GUnzip, InvalidHeaderCrc) {
    htp_status_t rc = decompressFile("gztest-15-invalid-fhcrc.gz");
    ASSERT_EQ(rc, HTP_OK);
    ASSERT_TRUE(output != NULL);
    ASSERT_TRUE(bstr_cmp(o_boxing_wizards, output) == 0);
}
<|endoftext|>