<commit_before>/**
 * @file Cosa/Periodic.hh
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2012-2015, Mikael Patel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * This file is part of the Arduino Che Cosa project.
 */

#ifndef COSA_PERIODIC_HH
#define COSA_PERIODIC_HH

#include "Cosa/Types.h"
#include "Cosa/Job.hh"

/**
 * Periodic function handler. Syntactic sugar for periodical jobs.
 * Subclass and implement the virtual method run() as the function to
 * be executed periodically. The scheduler defines the time base;
 * the alarm scheduler uses seconds, the watchdog job scheduler
 * milli-seconds and the real-time clock micro-seconds.
 *
 * @section See Also
 * For details on handling of time units see Job.hh. This execution
 * pattern is also available in the FSM (Finite State Machine) class.
 */
class Periodic : public Job {
public:
  /**
   * Construct a periodic function handled by the given scheduler and
   * with the given period in the schedulers time base. The maximum
   * period is UINT32_MAX; 1.2 hours with RTC::Scheduler, 49 days with
   * Watchdog::Scheduler and 136 years with Alarm::Clock.
   * @param[in] scheduler for the periodic job.
   * @param[in] period of timeout.
   */
  Periodic(Job::Scheduler* scheduler, uint32_t period) :
    Job(scheduler),
    m_period(period)
  {}

  /**
   * Set timeout period.
   * @param[in] time period of timeout.
   */
  void period(uint32_t time)
    __attribute__((always_inline))
  {
    m_period = time;
  }

  /**
   * Get timeout period.
   * @return period of timeout.
   */
  uint32_t period() const
    __attribute__((always_inline))
  {
    return (m_period);
  }

  /**
   * Reschedule after a new period.
   */
  void reschedule()
  {
    if (m_period == 0) return;
    expire_after(m_period);
    start();
  }

protected:
  /**
   * @override{Event::Handler}
   * Periodic event handler; dispatch the run() function on
   * timeout events and reschedule the periodic job.
   * @param[in] type the type of event.
   * @param[in] value the event value.
   */
  virtual void on_event(uint8_t type, uint16_t value)
  {
    UNUSED(value);
    if (UNLIKELY(type != Event::TIMEOUT_TYPE)) return;
    run();
    reschedule();
  }

  /** Time period. Time unit is defined by the scheduler. */
  uint32_t m_period;
};

/**
 * Syntactic sugar for periodic blocks in the loop() function. Used in
 * the form:
 * @code
 * void loop()
 * {
 *   periodic(timer,period) {
 *     ...
 *   }
 *   ...
 * }
 * @endcode
 * May be used several times in the loop() function. The timer
 * variable is defined and available in the loop().
 * @param[in] timer variable.
 * @param[in] period in milli-seconds.
 * @note requires RTC.hh.
 */
#define periodic(timer,ms)						\
  static uint32_t timer = RTC::millis();				\
  for (int __UNIQUE(i) = 1;						\
       (__UNIQUE(i) != 0) && ((RTC::since(timer)) >= ms);		\
       __UNIQUE(i)--, timer += ms)

#endif
<commit_msg>Clean up.<commit_after>/**
 * @file Cosa/Periodic.hh
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2012-2015, Mikael Patel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * This file is part of the Arduino Che Cosa project.
 */

#ifndef COSA_PERIODIC_HH
#define COSA_PERIODIC_HH

#include "Cosa/Types.h"
#include "Cosa/Job.hh"

/**
 * Periodic function handler. Syntactic sugar for periodical jobs.
 * Subclass and implement the virtual method run() as the function to
 * be executed periodically. The scheduler defines the time base;
 * the alarm scheduler uses seconds, the watchdog job scheduler
 * milli-seconds and the real-time clock micro-seconds.
 *
 * @section See Also
 * For details on handling of time units see Job.hh. This execution
 * pattern is also available in the FSM (Finite State Machine) class.
 */
class Periodic : public Job {
public:
  /**
   * Construct a periodic function handled by the given scheduler and
   * with the given period in the schedulers time base. The maximum
   * period is UINT32_MAX; 1.2 hours with RTC::Scheduler, 49 days with
   * Watchdog::Scheduler and 136 years with Alarm::Clock.
   * @param[in] scheduler for the periodic job.
   * @param[in] period of timeout.
   */
  Periodic(Job::Scheduler* scheduler, uint32_t period) :
    Job(scheduler),
    m_period(period)
  {}

  /**
   * Set timeout period.
   * @param[in] time period of timeout.
   */
  void period(uint32_t time)
    __attribute__((always_inline))
  {
    m_period = time;
  }

  /**
   * Get timeout period.
   * @return period of timeout.
   */
  uint32_t period() const
    __attribute__((always_inline))
  {
    return (m_period);
  }

  /**
   * Reschedule after a new period.
   */
  void reschedule()
  {
    if (m_period == 0) return;
    expire_after(m_period);
    start();
  }

protected:
  /**
   * @override{Event::Handler}
   * Periodic event handler; dispatch the run() function on
   * timeout events and reschedule the periodic job.
   * @param[in] type the type of event.
   * @param[in] value the event value.
   */
  virtual void on_event(uint8_t type, uint16_t value)
  {
    UNUSED(value);
    if (UNLIKELY(type != Event::TIMEOUT_TYPE)) return;
    run();
    reschedule();
  }

  /** Time period. Time unit is defined by the scheduler. */
  uint32_t m_period;
};

/**
 * Syntactic sugar for periodic blocks in the loop() function. Used in
 * the form:
 * @code
 * void loop()
 * {
 *   periodic(timer,period) {
 *     ...
 *   }
 *   ...
 * }
 * @endcode
 * May be used several times in the loop() function. The timer
 * variable is defined and available in the loop().
 * @param[in] timer variable.
 * @param[in] period in milli-seconds.
 * @note requires RTC.hh.
 */
#define periodic(timer,ms)						\
  static uint32_t timer = RTC::millis();				\
  for (int __UNIQUE(i) = 1;						\
       (__UNIQUE(i) != 0) && ((RTC::since(timer)) >= ms);		\
       __UNIQUE(i)--, timer += ms)

#endif
<|endoftext|>


<commit_before>/**
 * @file Cosa/Resource.hh
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2015, Mikael Patel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * This file is part of the Arduino Che Cosa project.
 */

#ifndef COSA_RESOURCE_HH
#define COSA_RESOURCE_HH

#include "Cosa/Types.h"

/**
 * Abstract Resource Handler. Secure acquire and release of resources.
 */
class Resource {
public:
  /**
   * Construct Resource Handler.
   */
  Resource() :
    m_busy(false)
  {}

  /**
   * Acquire the resource. Wait until the resource is not busy.
   * Mark as busy and run call on_acquire() in mutual context.
   */
  void acquire()
  {
    uint8_t key = lock();
    while (UNLIKELY(m_busy)) {
      unlock(key);
      yield();
      key = lock();
    }
    m_busy = true;
    on_acquire();
    unlock(key);
  }

  /**
   * Release the resource. Call on_release() in mutex context.
   */
  void release()
  {
    uint8_t key = lock();
    on_release();
    m_busy = false;
    unlock(key);
  }

protected:
  /**
   * @override{Resource}
   * Resource extension on acquire.
   */
  virtual void on_acquire() = 0;

  /**
   * @override{Resource}
   * Resource extension on release.
   */
  virtual void on_release() = 0;

private:
  volatile bool m_busy;
};
#endif

<commit_msg>Add try_acquire() to Resource.<commit_after>/**
 * @file Cosa/Resource.hh
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2015, Mikael Patel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * This file is part of the Arduino Che Cosa project.
 */

#ifndef COSA_RESOURCE_HH
#define COSA_RESOURCE_HH

#include "Cosa/Types.h"

/**
 * Abstract Resource Handler. Secure acquire and release of resources.
 */
class Resource {
public:
  /**
   * Construct Resource Handler.
   */
  Resource() :
    m_busy(false)
  {}

  /**
   * Acquire the resource. Wait until the resource is not busy.
   * Mark as busy and call on_acquire() in synchronized context.
   */
  void acquire()
  {
    uint8_t key = lock(m_busy);
    on_acquire();
    unlock(key);
  }

  /**
   * Try to acquire the resource. If successful, mark as busy and call
   * on_acquire() in synchronized context.
   * @return bool.
   */
  bool try_acquire()
  {
    synchronized {
      if (m_busy) return (false);
      m_busy = true;
      on_acquire();
    }
  }

  /**
   * Release the resource. Call on_release() in synchronized context
   * and mark the resource as available.
   */
  void release()
  {
    synchronized {
      on_release();
      m_busy = false;
    }
  }

protected:
  /**
   * @override{Resource}
   * Resource extension on acquire.
   */
  virtual void on_acquire() = 0;

  /**
   * @override{Resource}
   * Resource extension on release.
   */
  virtual void on_release() = 0;

private:
  volatile bool m_busy;
};
#endif

<|endoftext|>


<commit_before>#include "hornet/java.hh"

#include <hornet/vm.hh>

#include <classfile_constants.h>
#include <cassert>
#include <stack>

namespace hornet {

bool verify_method(std::shared_ptr<method> method)
{
    uint16_t pc = 0;

    for (;;) {
        uint8_t opc = method->code[pc++];

        switch (opc) {
        case JVM_OPC_aload_0:
        case JVM_OPC_aload_1:
        case JVM_OPC_aload_2:
        case JVM_OPC_aload_3: {
            uint16_t idx = opc - JVM_OPC_aload_0;
            if (idx >= method->max_locals)
                return false;
        }
        case JVM_OPC_return: {
            return true;
        }
        default:
            fprintf(stderr, "error: Unsupported bytecode: %u\n", opc);
            return false;
        }
    }
}

}
<commit_msg>java: Fix verifier for StartupTest<commit_after>#include "hornet/java.hh"

#include <hornet/vm.hh>

#include <classfile_constants.h>
#include <cassert>
#include <stack>

namespace hornet {

bool verify_method(std::shared_ptr<method> method)
{
    uint16_t pc = 0;

    for (;;) {
        if (pc >= method->code_length)
            break;

        uint8_t opc = method->code[pc++];

        switch (opc) {
        case JVM_OPC_aload_0:
        case JVM_OPC_aload_1:
        case JVM_OPC_aload_2:
        case JVM_OPC_aload_3: {
            uint16_t idx = opc - JVM_OPC_aload_0;
            if (idx >= method->max_locals)
                return false;
            break;
        }
        case JVM_OPC_return: {
            break;
        }
        case JVM_OPC_invokespecial: {
            pc += 2;
            break;
        }
        default:
            fprintf(stderr, "error: Unsupported bytecode: %u\n", opc);
            return false;
        }
    }

    return true;
}

}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// HierarchySymbols.cpp
// Contains hierarchy-related symbol definitions.
//
// File is under the MIT license; see LICENSE for details.
//------------------------------------------------------------------------------
#include "HierarchySymbols.h"

#include "json.hpp"

#include "compilation/Compilation.h"
#include "util/StackContainer.h"

namespace slang {

PackageSymbol& PackageSymbol::fromSyntax(Compilation& compilation, const ModuleDeclarationSyntax& syntax) {
    auto result = compilation.emplace<PackageSymbol>(compilation, syntax.header.name.valueText(),
                                                     syntax.header.name.location());
    for (auto member : syntax.members)
        result->addMembers(*member);
    return *result;
}

void InstanceSymbol::fromSyntax(Compilation& compilation, const HierarchyInstantiationSyntax& syntax,
                                LookupLocation location, const Scope& scope, SmallVector<const Symbol*>& results) {

    auto definition = compilation.getDefinition(syntax.type.valueText(), scope);
    if (!definition) {
        // TODO: error
        return;
    }

    SmallMap<string_view, const ExpressionSyntax*, 8> paramOverrides;
    if (syntax.parameters) {
        // Build up data structures to easily index the parameter assignments. We need to handle
        // both ordered assignment as well as named assignment, though a specific instance can only
        // use one method or the other.
        bool hasParamAssignments = false;
        bool orderedAssignments = true;
        SmallVectorSized<const OrderedArgumentSyntax*, 8> orderedParams;
        SmallMap<string_view, std::pair<const NamedArgumentSyntax*, bool>, 8> namedParams;

        // TODO: syntax node names here are dumb
        for (auto paramBase : syntax.parameters->parameters.parameters) {
            bool isOrdered = paramBase->kind == SyntaxKind::OrderedArgument;
            if (!hasParamAssignments) {
                hasParamAssignments = true;
                orderedAssignments = isOrdered;
            }
            else if (isOrdered != orderedAssignments) {
                compilation.addError(DiagCode::MixingOrderedAndNamedParams, paramBase->getFirstToken().location());
                break;
            }

            if (isOrdered)
                orderedParams.append(&paramBase->as<OrderedArgumentSyntax>());
            else {
                const NamedArgumentSyntax& nas = paramBase->as<NamedArgumentSyntax>();
                auto pair = namedParams.emplace(nas.name.valueText(), std::make_pair(&nas, false));
                if (!pair.second) {
                    auto& diag = compilation.addError(DiagCode::DuplicateParamAssignment, nas.name.location());
                    diag << nas.name.valueText();
                    diag.addNote(DiagCode::NotePreviousUsage, pair.first->second.first->name.location());
                }
            }
        }

        // For each parameter assignment we have, match it up to a real parameter
        if (orderedAssignments) {
            uint32_t orderedIndex = 0;
            for (auto param : definition->parameters) {
                if (orderedIndex >= orderedParams.size())
                    break;

                if (param.isLocal)
                    continue;

                paramOverrides.emplace(param.name, &orderedParams[orderedIndex++]->expr);
            }

            // Make sure there aren't extra param assignments for non-existent params.
            if (orderedIndex < orderedParams.size()) {
                auto loc = orderedParams[orderedIndex]->getFirstToken().location();
                auto& diag = compilation.addError(DiagCode::TooManyParamAssignments, loc);
                diag << definition->name;
                diag << orderedParams.size();
                diag << orderedIndex;
            }
        }
        else {
            // Otherwise handle named assignments.
            for (auto param : definition->parameters) {
                auto it = namedParams.find(param.name);
                if (it == namedParams.end())
                    continue;

                const NamedArgumentSyntax* arg = it->second.first;
                it->second.second = true;
                if (param.isLocal) {
                    // Can't assign to localparams, so this is an error.
                    DiagCode code = param.isPort ? DiagCode::AssignedToLocalPortParam : DiagCode::AssignedToLocalBodyParam;
                    auto& diag = compilation.addError(code, arg->name.location());
                    diag.addNote(DiagCode::NoteDeclarationHere, param.location);
                    continue;
                }

                // It's allowed to have no initializer in the assignment; it means to just use the default
                if (!arg->expr)
                    continue;

                paramOverrides.emplace(param.name, arg->expr);
            }

            for (const auto& pair : namedParams) {
                // We marked all the args that we used, so anything left over is a param assignment
                // for a non-existent parameter.
                if (!pair.second.second) {
                    auto& diag = compilation.addError(DiagCode::ParameterDoesNotExist, pair.second.first->name.location());
                    diag << pair.second.first->name.valueText();
                    diag << definition->name;
                }
            }
        }
    }

    // Determine values for all parameters now so that they can be shared between instances.
    SmallVectorSized<ParameterMetadata, 8> params;
    for (const auto& decl : definition->parameters) {
        std::tuple<const Type*, ConstantValue> typeAndValue(nullptr, nullptr);
        if (auto it = paramOverrides.find(decl.name); it != paramOverrides.end())
            typeAndValue = ParameterSymbol::evaluate(*decl.type, *it->second, location, scope);
        else if (!decl.initializer && !decl.isLocal && decl.isPort) {
            auto& diag = compilation.addError(DiagCode::ParamHasNoValue, syntax.getFirstToken().location());
            diag << definition->name;
            diag << decl.name;
        }

        params.emplace(ParameterMetadata { &decl, std::get<0>(typeAndValue), std::move(std::get<1>(typeAndValue)) });
    }

    for (auto instanceSyntax : syntax.instances) {
        const Symbol* inst;
        switch (definition->syntax.kind) {
            case SyntaxKind::ModuleDeclaration:
                inst = &ModuleInstanceSymbol::instantiate(compilation, instanceSyntax->name.valueText(),
                                                          instanceSyntax->name.location(), *definition, params);
                break;
            case SyntaxKind::InterfaceDeclaration:
                inst = &InterfaceInstanceSymbol::instantiate(compilation, instanceSyntax->name.valueText(),
                                                             instanceSyntax->name.location(), *definition, params);
                break;
            default:
                THROW_UNREACHABLE;
        }

        // TODO: instance arrays
        results.append(inst);
    }
}

bool InstanceSymbol::isKind(SymbolKind kind) {
    switch (kind) {
        case SymbolKind::ModuleInstance:
        case SymbolKind::InterfaceInstance:
        case SymbolKind::Program:
            return true;
        default:
            return false;
    }
}

void InstanceSymbol::populate(const Definition& definition, span<const ParameterMetadata> parameters) {
    // Add all port parameters as members first.
    auto paramIt = parameters.begin();
    while (paramIt != parameters.end()) {
        auto decl = paramIt->decl;
        if (!decl->isPort)
            break;

        auto& param = ParameterSymbol::fromDecl(getCompilation(), *decl);
        addMember(param);

        if (paramIt->type) {
            param.setType(*paramIt->type);
            param.setValue(paramIt->value);
        }
        paramIt++;
    }

    for (auto member : definition.syntax.members) {
        // If this is a parameter declaration, we should already have metadata for it in our parameters list.
        // The list is given in declaration order, so we should be be able to move through them incrementally.
        if (member->kind != SyntaxKind::ParameterDeclarationStatement)
            addMembers(*member);
        else {
            for (auto declarator : member->as<ParameterDeclarationStatementSyntax>().parameter.declarators) {
                (void)declarator;
                ASSERT(paramIt != parameters.end());

                auto decl = paramIt->decl;
                auto& param = ParameterSymbol::fromDecl(getCompilation(), *decl);
                if (paramIt->type) {
                    param.setType(*paramIt->type);
                    param.setValue(paramIt->value);
                }
                addMember(param);
                paramIt++;
            }
        }
    }
}

ModuleInstanceSymbol& ModuleInstanceSymbol::instantiate(Compilation& compilation, string_view name,
                                                        SourceLocation loc, const Definition& definition) {
    SmallVectorSized<ParameterMetadata, 8> params;
    for (const auto& decl : definition.parameters) {
        // This function should only be called for definitions where all parameters have defaults.
        ASSERT(decl.initializer);
        params.emplace(ParameterMetadata { &decl, nullptr, nullptr });
    }

    return instantiate(compilation, name, loc, definition, params);
}

ModuleInstanceSymbol& ModuleInstanceSymbol::instantiate(Compilation& compilation, string_view name,
                                                        SourceLocation loc, const Definition& definition,
                                                        span<const ParameterMetadata> parameters) {

    auto instance = compilation.emplace<ModuleInstanceSymbol>(compilation, name, loc);
    instance->populate(definition, parameters);
    return *instance;
}

InterfaceInstanceSymbol& InterfaceInstanceSymbol::instantiate(Compilation& compilation, string_view name,
                                                              SourceLocation loc, const Definition& definition,
                                                              span<const ParameterMetadata> parameters) {

    auto instance = compilation.emplace<InterfaceInstanceSymbol>(compilation, name, loc);
    instance->populate(definition, parameters);
    return *instance;
}

SequentialBlockSymbol& SequentialBlockSymbol::fromSyntax(Compilation& compilation,
                                                         const BlockStatementSyntax& syntax) {
    auto result = compilation.emplace<SequentialBlockSymbol>(compilation, syntax.begin.location());
    result->setBody(syntax.items);
    return *result;
}

ProceduralBlockSymbol& ProceduralBlockSymbol::fromSyntax(Compilation& compilation,
                                                         const ProceduralBlockSyntax& syntax) {
    auto kind = SemanticFacts::getProceduralBlockKind(syntax.kind);
    auto result = compilation.emplace<ProceduralBlockSymbol>(compilation,
                                                             syntax.keyword.location(),
                                                             kind);
    result->setBody(syntax.statement);
    return *result;
}

void ProceduralBlockSymbol::toJson(json& j) const {
    // TODO: stringify
    j["procedureKind"] = procedureKind;
}

static string_view getGenerateBlockName(const SyntaxNode& node) {
    if (node.kind != SyntaxKind::GenerateBlock)
        return "";

    // Try to find a name for this block. Generate blocks allow the name to be specified twice
    // (for no good reason) so check both locations. The parser has already checked for inconsistencies here.
    const GenerateBlockSyntax& block = node.as<GenerateBlockSyntax>();
    if (block.label)
        return block.label->name.valueText();

    if (block.beginName)
        return block.beginName->name.valueText();

    return "";
}

GenerateBlockSymbol* GenerateBlockSymbol::fromSyntax(Compilation& compilation, const IfGenerateSyntax& syntax,
                                                     LookupLocation location, const Scope& parent) {
    // TODO: better error checking
    BindContext bindContext(parent, location, BindFlags::Constant);
    const auto& cond = Expression::bind(compilation, syntax.condition, bindContext);
    if (!cond.constant)
        return nullptr;

    const SVInt& value = cond.constant->integer();

    const SyntaxNode* memberSyntax = nullptr;
    if ((logic_t)value)
        memberSyntax = &syntax.block;
    else if (syntax.elseClause)
        memberSyntax = &syntax.elseClause->clause;
    else
        return nullptr;

    string_view name = getGenerateBlockName(*memberSyntax);
    SourceLocation loc = memberSyntax->getFirstToken().location();

    auto block = compilation.emplace<GenerateBlockSymbol>(compilation, name, loc);
    block->addMembers(*memberSyntax);
    return block;
}

GenerateBlockArraySymbol& GenerateBlockArraySymbol::fromSyntax(Compilation& compilation,
                                                               const LoopGenerateSyntax& syntax,
                                                               LookupLocation location,
                                                               const Scope& parent) {
    // If the loop initializer has a genvar keyword, we can use it directly. Otherwise
    // we need to do a lookup to make sure we have the actual genvar.
    // TODO: do the actual lookup

    string_view name = getGenerateBlockName(syntax.block);
    SourceLocation loc = syntax.block.getFirstToken().location();
    auto result = compilation.emplace<GenerateBlockArraySymbol>(compilation, "", SourceLocation());

    // Initialize the genvar
    BindContext bindContext(parent, location, BindFlags::Constant);
    const auto& initial = Expression::bind(compilation, syntax.initialExpr, bindContext);
    if (!initial.constant)
        return *result;

    // Fabricate a local variable that will serve as the loop iteration variable.
    SequentialBlockSymbol iterScope(compilation, SourceLocation());
    VariableSymbol local { syntax.identifier.valueText(), syntax.identifier.location() };
    local.type = compilation.getIntType();
    iterScope.addMember(local);

    // Bind the stop and iteration expressions so we can reuse them on each iteration.
    const auto& stopExpr = Expression::bind(compilation, syntax.stopExpr, BindContext(iterScope, LookupLocation::max));
    const auto& iterExpr = Expression::bind(compilation, syntax.iterationExpr, BindContext(iterScope, LookupLocation::max));

    // Create storage for the iteration variable.
    EvalContext context;
    auto genvar = context.createLocal(&local, *initial.constant);

    // Generate blocks!
    SmallVectorSized<const Symbol*, 16> arrayEntries;
    for (; stopExpr.evalBool(context); iterExpr.eval(context)) {
        // Spec: each generate block gets their own scope, with an implicit
        // localparam of the same name as the genvar.
        // TODO: scope name
        auto block = compilation.emplace<GenerateBlockSymbol>(compilation, "", SourceLocation());
        auto implicitParam = compilation.emplace<ParameterSymbol>(syntax.identifier.valueText(),
                                                                  syntax.identifier.location(),
                                                                  true /* isLocal */,
                                                                  false /* isPort */);
        block->addMember(*implicitParam);
        block->addMembers(syntax.block);
        result->addMember(*block);

        implicitParam->setType(*local.type);
        implicitParam->setValue(*genvar);
    }

    return *result;
}

}
<commit_msg>Fix unused variables<commit_after>//------------------------------------------------------------------------------
// HierarchySymbols.cpp
// Contains hierarchy-related symbol definitions.
//
// File is under the MIT license; see LICENSE for details.
//------------------------------------------------------------------------------
#include "HierarchySymbols.h"

#include "json.hpp"

#include "compilation/Compilation.h"
#include "util/StackContainer.h"

namespace slang {

PackageSymbol& PackageSymbol::fromSyntax(Compilation& compilation, const ModuleDeclarationSyntax& syntax) {
    auto result = compilation.emplace<PackageSymbol>(compilation, syntax.header.name.valueText(),
                                                     syntax.header.name.location());
    for (auto member : syntax.members)
        result->addMembers(*member);
    return *result;
}

void InstanceSymbol::fromSyntax(Compilation& compilation, const HierarchyInstantiationSyntax& syntax,
                                LookupLocation location, const Scope& scope, SmallVector<const Symbol*>& results) {

    auto definition = compilation.getDefinition(syntax.type.valueText(), scope);
    if (!definition) {
        // TODO: error
        return;
    }

    SmallMap<string_view, const ExpressionSyntax*, 8> paramOverrides;
    if (syntax.parameters) {
        // Build up data structures to easily index the parameter assignments. We need to handle
        // both ordered assignment as well as named assignment, though a specific instance can only
        // use one method or the other.
        bool hasParamAssignments = false;
        bool orderedAssignments = true;
        SmallVectorSized<const OrderedArgumentSyntax*, 8> orderedParams;
        SmallMap<string_view, std::pair<const NamedArgumentSyntax*, bool>, 8> namedParams;

        // TODO: syntax node names here are dumb
        for (auto paramBase : syntax.parameters->parameters.parameters) {
            bool isOrdered = paramBase->kind == SyntaxKind::OrderedArgument;
            if (!hasParamAssignments) {
                hasParamAssignments = true;
                orderedAssignments = isOrdered;
            }
            else if (isOrdered != orderedAssignments) {
                compilation.addError(DiagCode::MixingOrderedAndNamedParams, paramBase->getFirstToken().location());
                break;
            }

            if (isOrdered)
                orderedParams.append(&paramBase->as<OrderedArgumentSyntax>());
            else {
                const NamedArgumentSyntax& nas = paramBase->as<NamedArgumentSyntax>();
                auto pair = namedParams.emplace(nas.name.valueText(), std::make_pair(&nas, false));
                if (!pair.second) {
                    auto& diag = compilation.addError(DiagCode::DuplicateParamAssignment, nas.name.location());
                    diag << nas.name.valueText();
                    diag.addNote(DiagCode::NotePreviousUsage, pair.first->second.first->name.location());
                }
            }
        }

        // For each parameter assignment we have, match it up to a real parameter
        if (orderedAssignments) {
            uint32_t orderedIndex = 0;
            for (auto param : definition->parameters) {
                if (orderedIndex >= orderedParams.size())
                    break;

                if (param.isLocal)
                    continue;

                paramOverrides.emplace(param.name, &orderedParams[orderedIndex++]->expr);
            }

            // Make sure there aren't extra param assignments for non-existent params.
            if (orderedIndex < orderedParams.size()) {
                auto loc = orderedParams[orderedIndex]->getFirstToken().location();
                auto& diag = compilation.addError(DiagCode::TooManyParamAssignments, loc);
                diag << definition->name;
                diag << orderedParams.size();
                diag << orderedIndex;
            }
        }
        else {
            // Otherwise handle named assignments.
            for (auto param : definition->parameters) {
                auto it = namedParams.find(param.name);
                if (it == namedParams.end())
                    continue;

                const NamedArgumentSyntax* arg = it->second.first;
                it->second.second = true;
                if (param.isLocal) {
                    // Can't assign to localparams, so this is an error.
                    DiagCode code = param.isPort ? DiagCode::AssignedToLocalPortParam : DiagCode::AssignedToLocalBodyParam;
                    auto& diag = compilation.addError(code, arg->name.location());
                    diag.addNote(DiagCode::NoteDeclarationHere, param.location);
                    continue;
                }

                // It's allowed to have no initializer in the assignment; it means to just use the default
                if (!arg->expr)
                    continue;

                paramOverrides.emplace(param.name, arg->expr);
            }

            for (const auto& pair : namedParams) {
                // We marked all the args that we used, so anything left over is a param assignment
                // for a non-existent parameter.
                if (!pair.second.second) {
                    auto& diag = compilation.addError(DiagCode::ParameterDoesNotExist, pair.second.first->name.location());
                    diag << pair.second.first->name.valueText();
                    diag << definition->name;
                }
            }
        }
    }

    // Determine values for all parameters now so that they can be shared between instances.
    SmallVectorSized<ParameterMetadata, 8> params;
    for (const auto& decl : definition->parameters) {
        std::tuple<const Type*, ConstantValue> typeAndValue(nullptr, nullptr);
        if (auto it = paramOverrides.find(decl.name); it != paramOverrides.end())
            typeAndValue = ParameterSymbol::evaluate(*decl.type, *it->second, location, scope);
        else if (!decl.initializer && !decl.isLocal && decl.isPort) {
            auto& diag = compilation.addError(DiagCode::ParamHasNoValue, syntax.getFirstToken().location());
            diag << definition->name;
            diag << decl.name;
        }

        params.emplace(ParameterMetadata { &decl, std::get<0>(typeAndValue), std::move(std::get<1>(typeAndValue)) });
    }

    for (auto instanceSyntax : syntax.instances) {
        const Symbol* inst;
        switch (definition->syntax.kind) {
            case SyntaxKind::ModuleDeclaration:
                inst = &ModuleInstanceSymbol::instantiate(compilation, instanceSyntax->name.valueText(),
                                                          instanceSyntax->name.location(), *definition, params);
                break;
            case SyntaxKind::InterfaceDeclaration:
                inst = &InterfaceInstanceSymbol::instantiate(compilation, instanceSyntax->name.valueText(),
                                                             instanceSyntax->name.location(), *definition, params);
                break;
            default:
                THROW_UNREACHABLE;
        }

        // TODO: instance arrays
        results.append(inst);
    }
}

bool InstanceSymbol::isKind(SymbolKind kind) {
    switch (kind) {
        case SymbolKind::ModuleInstance:
        case SymbolKind::InterfaceInstance:
        case SymbolKind::Program:
            return true;
        default:
            return false;
    }
}

void InstanceSymbol::populate(const Definition& definition, span<const ParameterMetadata> parameters) {
    // Add all port parameters as members first.
    auto paramIt = parameters.begin();
    while (paramIt != parameters.end()) {
        auto decl = paramIt->decl;
        if (!decl->isPort)
            break;

        auto& param = ParameterSymbol::fromDecl(getCompilation(), *decl);
        addMember(param);

        if (paramIt->type) {
            param.setType(*paramIt->type);
            param.setValue(paramIt->value);
        }
        paramIt++;
    }

    for (auto member : definition.syntax.members) {
        // If this is a parameter declaration, we should already have metadata for it in our parameters list.
        // The list is given in declaration order, so we should be be able to move through them incrementally.
        if (member->kind != SyntaxKind::ParameterDeclarationStatement)
            addMembers(*member);
        else {
            for (auto declarator : member->as<ParameterDeclarationStatementSyntax>().parameter.declarators) {
                (void)declarator;
                ASSERT(paramIt != parameters.end());

                auto decl = paramIt->decl;
                auto& param = ParameterSymbol::fromDecl(getCompilation(), *decl);
                if (paramIt->type) {
                    param.setType(*paramIt->type);
                    param.setValue(paramIt->value);
                }
                addMember(param);
                paramIt++;
            }
        }
    }
}

ModuleInstanceSymbol& ModuleInstanceSymbol::instantiate(Compilation& compilation, string_view name,
                                                        SourceLocation loc, const Definition& definition) {
    SmallVectorSized<ParameterMetadata, 8> params;
    for (const auto& decl : definition.parameters) {
        // This function should only be called for definitions where all parameters have defaults.
        ASSERT(decl.initializer);
        params.emplace(ParameterMetadata { &decl, nullptr, nullptr });
    }

    return instantiate(compilation, name, loc, definition, params);
}

ModuleInstanceSymbol& ModuleInstanceSymbol::instantiate(Compilation& compilation, string_view name,
                                                        SourceLocation loc, const Definition& definition,
                                                        span<const ParameterMetadata> parameters) {

    auto instance = compilation.emplace<ModuleInstanceSymbol>(compilation, name, loc);
    instance->populate(definition, parameters);
    return *instance;
}

InterfaceInstanceSymbol& InterfaceInstanceSymbol::instantiate(Compilation& compilation, string_view name,
                                                              SourceLocation loc, const Definition& definition,
                                                              span<const ParameterMetadata> parameters) {

    auto instance = compilation.emplace<InterfaceInstanceSymbol>(compilation, name, loc);
    instance->populate(definition, parameters);
    return *instance;
}

SequentialBlockSymbol& SequentialBlockSymbol::fromSyntax(Compilation& compilation,
                                                         const BlockStatementSyntax& syntax) {
    auto result = compilation.emplace<SequentialBlockSymbol>(compilation, syntax.begin.location());
    result->setBody(syntax.items);
    return *result;
}

ProceduralBlockSymbol& ProceduralBlockSymbol::fromSyntax(Compilation& compilation,
                                                         const ProceduralBlockSyntax& syntax) {
    auto kind = SemanticFacts::getProceduralBlockKind(syntax.kind);
    auto result = compilation.emplace<ProceduralBlockSymbol>(compilation,
                                                             syntax.keyword.location(),
                                                             kind);
    result->setBody(syntax.statement);
    return *result;
}

void ProceduralBlockSymbol::toJson(json& j) const {
    // TODO: stringify
    j["procedureKind"] = procedureKind;
}

static string_view getGenerateBlockName(const SyntaxNode& node) {
    if (node.kind != SyntaxKind::GenerateBlock)
        return "";

    // Try to find a name for this block. Generate blocks allow the name to be specified twice
    // (for no good reason) so check both locations. The parser has already checked for inconsistencies here.
    const GenerateBlockSyntax& block = node.as<GenerateBlockSyntax>();
    if (block.label)
        return block.label->name.valueText();

    if (block.beginName)
        return block.beginName->name.valueText();

    return "";
}

GenerateBlockSymbol* GenerateBlockSymbol::fromSyntax(Compilation& compilation, const IfGenerateSyntax& syntax,
                                                     LookupLocation location, const Scope& parent) {
    // TODO: better error checking
    BindContext bindContext(parent, location, BindFlags::Constant);
    const auto& cond = Expression::bind(compilation, syntax.condition, bindContext);
    if (!cond.constant)
        return nullptr;

    const SVInt& value = cond.constant->integer();

    const SyntaxNode* memberSyntax = nullptr;
    if ((logic_t)value)
        memberSyntax = &syntax.block;
    else if (syntax.elseClause)
        memberSyntax = &syntax.elseClause->clause;
    else
        return nullptr;

    string_view name = getGenerateBlockName(*memberSyntax);
    SourceLocation loc = memberSyntax->getFirstToken().location();

    auto block = compilation.emplace<GenerateBlockSymbol>(compilation, name, loc);
    block->addMembers(*memberSyntax);
    return block;
}

GenerateBlockArraySymbol& GenerateBlockArraySymbol::fromSyntax(Compilation& compilation,
                                                               const LoopGenerateSyntax& syntax,
                                                               LookupLocation location,
                                                               const Scope& parent) {
    // If the loop initializer has a genvar keyword, we can use it directly. Otherwise
    // we need to do a lookup to make sure we have the actual genvar.
    // TODO: do the actual lookup

    string_view name = getGenerateBlockName(syntax.block);
    SourceLocation loc = syntax.block.getFirstToken().location();
    auto result = compilation.emplace<GenerateBlockArraySymbol>(compilation, name, loc);

    // Initialize the genvar
    BindContext bindContext(parent, location, BindFlags::Constant);
    const auto& initial = Expression::bind(compilation, syntax.initialExpr, bindContext);
    if (!initial.constant)
        return *result;

    // Fabricate a local variable that will serve as the loop iteration variable.
    SequentialBlockSymbol iterScope(compilation, SourceLocation());
    VariableSymbol local { syntax.identifier.valueText(), syntax.identifier.location() };
    local.type = compilation.getIntType();
    iterScope.addMember(local);

    // Bind the stop and iteration expressions so we can reuse them on each iteration.
    const auto& stopExpr = Expression::bind(compilation, syntax.stopExpr, BindContext(iterScope, LookupLocation::max));
    const auto& iterExpr = Expression::bind(compilation, syntax.iterationExpr, BindContext(iterScope, LookupLocation::max));

    // Create storage for the iteration variable.
    EvalContext context;
    auto genvar = context.createLocal(&local, *initial.constant);

    // Generate blocks!
    SmallVectorSized<const Symbol*, 16> arrayEntries;
    for (; stopExpr.evalBool(context); iterExpr.eval(context)) {
        // Spec: each generate block gets their own scope, with an implicit
        // localparam of the same name as the genvar.
        // TODO: scope name
        auto block = compilation.emplace<GenerateBlockSymbol>(compilation, "", SourceLocation());
        auto implicitParam = compilation.emplace<ParameterSymbol>(syntax.identifier.valueText(),
                                                                  syntax.identifier.location(),
                                                                  true /* isLocal */,
                                                                  false /* isPort */);
        block->addMember(*implicitParam);
        block->addMembers(syntax.block);
        result->addMember(*block);

        implicitParam->setType(*local.type);
        implicitParam->setValue(*genvar);
    }

    return *result;
}

}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2010, Willow Garage, 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 Willow Garage, 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 OWNER 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.
 */

#include "triangle_list_marker.h"

#include "marker_selection_handler.h"
#include "rviz/default_plugin/marker_display.h"
#include "rviz/selection/selection_manager.h"

#include "rviz/visualization_manager.h"
#include "rviz/mesh_loader.h"
#include "marker_display.h"

#include <OGRE/OgreSceneNode.h>
#include <OGRE/OgreSceneManager.h>
#include <OGRE/OgreManualObject.h>
#include <OGRE/OgreMaterialManager.h>
#include <OGRE/OgreTextureManager.h>
#include <OGRE/OgreTechnique.h>

namespace rviz
{

TriangleListMarker::TriangleListMarker(MarkerDisplay* owner, VisualizationManager* manager, Ogre::SceneNode* parent_node)
: MarkerBase(owner, manager, parent_node)
, manual_object_(0)
{
}

TriangleListMarker::~TriangleListMarker()
{
  vis_manager_->getSceneManager()->destroyManualObject(manual_object_);

  for (size_t i = 0; i < material_->getNumTechniques(); ++i)
  {
    Ogre::Technique* t = material_->getTechnique(i);
    // hack hack hack, really need to do a shader-based way of picking, rather than
    // creating a texture for each object
    if (t->getSchemeName() == "Pick")
    {
      Ogre::TextureManager::getSingleton().remove(t->getPass(0)->getTextureUnitState(0)->getTextureName());
    }
  }

  material_->unload();
  Ogre::MaterialManager::getSingleton().remove(material_->getName());
}

void TriangleListMarker::onNewMessage(const MarkerConstPtr& old_message, const MarkerConstPtr& new_message)
{
  ROS_ASSERT(new_message->type == visualization_msgs::Marker::TRIANGLE_LIST);

  if (!manual_object_)
  {
    static uint32_t count = 0;
    std::stringstream ss;
    ss << "Triangle List Marker" << count++;
    manual_object_ = vis_manager_->getSceneManager()->createManualObject(ss.str());
    scene_node_->attachObject(manual_object_);

    ss << "Material";
    material_name_ = ss.str();
    material_ = Ogre::MaterialManager::getSingleton().create( material_name_, ROS_PACKAGE_NAME );
    material_->setReceiveShadows(false);
    material_->getTechnique(0)->setLightingEnabled(true);
    material_->setCullingMode(Ogre::CULL_NONE);

    vis_manager_->getSelectionManager()->removeObject(coll_);

    SelectionManager* sel_man = vis_manager_->getSelectionManager();
    coll_ = sel_man->createHandle();
    sel_man->addPickTechnique(coll_, material_);
    sel_man->addObject( coll_, SelectionHandlerPtr(new MarkerSelectionHandler(this, MarkerID(new_message->ns, new_message->id))) );
  }

  size_t num_points = new_message->points.size();
  if ((num_points % 3) != 0)
  {
    std::stringstream ss;
    ss << "TriMesh marker [" << getStringID() << "] has a point count which is not divisible by 3 [" << num_points <<"]";
    if ( owner_ )
    {
      owner_->setMarkerStatus(getID(), status_levels::Error, ss.str());
    }
    ROS_DEBUG("%s", ss.str().c_str());

    manual_object_->clear();
    scene_node_->setVisible(false);
    return;
  }

  Ogre::Vector3 pos, scale;
  Ogre::Quaternion orient;
  transform(new_message, pos, orient, scale);

  if ( owner_ &&  (new_message->scale.x * new_message->scale.y * new_message->scale.z == 0.0f) )
  {
    owner_->setMarkerStatus(getID(), status_levels::Warn, "Scale of 0 in one of x/y/z");
  }

  setPosition(pos);
  setOrientation(orient);
  scene_node_->setScale(scale);

  // If we have the same number of tris as previously, just update the object
  if (old_message && num_points == old_message->points.size())
  {
    manual_object_->beginUpdate(0);
  }
  else // Otherwise clear it and begin anew
  {
    manual_object_->clear();
    manual_object_->estimateVertexCount(num_points);
    manual_object_->begin(material_name_, Ogre::RenderOperation::OT_TRIANGLE_LIST);
  }

  bool has_vertex_colors = new_message->colors.size() == num_points;

  if (has_vertex_colors)
  {
    for (size_t i = 0; i < num_points; ++i)
    {
      manual_object_->position(new_message->points[i].x, new_message->points[i].y, new_message->points[i].z);
      manual_object_->colour(new_message->colors[i].r, new_message->colors[i].g, new_message->colors[i].b, new_message->color.a);
    }
  }
  else
  {
    for (size_t i = 0; i < num_points; ++i)
    {
      manual_object_->position(new_message->points[i].x, new_message->points[i].y, new_message->points[i].z);
    }
  }

  manual_object_->end();

  if (has_vertex_colors)
  {
    material_->getTechnique(0)->setLightingEnabled(false);
  }
  else
  {
    material_->getTechnique(0)->setLightingEnabled(true);
    float r,g,b,a;
    r = new_message->color.r;
    g = new_message->color.g;
    b = new_message->color.b;
    a = new_message->color.a;
    material_->getTechnique(0)->setAmbient( r,g,b );
    material_->getTechnique(0)->setDiffuse( 0,0,0,a );
  }

  if ( new_message->color.a < 0.9998 )
  {
    material_->getTechnique(0)->setSceneBlending( Ogre::SBT_TRANSPARENT_ALPHA );
    material_->getTechnique(0)->setDepthWriteEnabled( false );
  }
  else
  {
    material_->getTechnique(0)->setSceneBlending( Ogre::SBT_REPLACE );
    material_->getTechnique(0)->setDepthWriteEnabled( true );
  }
}

S_MaterialPtr TriangleListMarker::getMaterials()
{
  S_MaterialPtr materials;
  materials.insert( material_ );
  return materials;
}

}

<commit_msg>rviz: fixed bug #5048: crash on bad triangle list marker.<commit_after>/*
 * Copyright (c) 2010, Willow Garage, 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 Willow Garage, 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 OWNER 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.
 */

#include "triangle_list_marker.h"

#include "marker_selection_handler.h"
#include "rviz/default_plugin/marker_display.h"
#include "rviz/selection/selection_manager.h"

#include "rviz/visualization_manager.h"
#include "rviz/mesh_loader.h"
#include "marker_display.h"

#include <OGRE/OgreSceneNode.h>
#include <OGRE/OgreSceneManager.h>
#include <OGRE/OgreManualObject.h>
#include <OGRE/OgreMaterialManager.h>
#include <OGRE/OgreTextureManager.h>
#include <OGRE/OgreTechnique.h>

namespace rviz
{

TriangleListMarker::TriangleListMarker(MarkerDisplay* owner, VisualizationManager* manager, Ogre::SceneNode* parent_node)
: MarkerBase(owner, manager, parent_node)
, manual_object_(0)
{
}

TriangleListMarker::~TriangleListMarker()
{
  vis_manager_->getSceneManager()->destroyManualObject(manual_object_);

  for (size_t i = 0; i < material_->getNumTechniques(); ++i)
  {
    Ogre::Technique* t = material_->getTechnique(i);
    // hack hack hack, really need to do a shader-based way of picking, rather than
    // creating a texture for each object
    if (t->getSchemeName() == "Pick")
    {
      Ogre::TextureManager::getSingleton().remove(t->getPass(0)->getTextureUnitState(0)->getTextureName());
    }
  }

  material_->unload();
  Ogre::MaterialManager::getSingleton().remove(material_->getName());
}

void TriangleListMarker::onNewMessage(const MarkerConstPtr& old_message, const MarkerConstPtr& new_message)
{
  ROS_ASSERT(new_message->type == visualization_msgs::Marker::TRIANGLE_LIST);

  size_t num_points = new_message->points.size();
  if( (num_points % 3) != 0 || num_points == 0 )
  {
    std::stringstream ss;
    if( num_points == 0 )
    {
      ss << "TriMesh marker [" << getStringID() << "] has no points.";
    }
    else
    {
      ss << "TriMesh marker [" << getStringID() << "] has a point count which is not divisible by 3 [" << num_points <<"]";
    }
    if ( owner_ )
    {
      owner_->setMarkerStatus(getID(), status_levels::Error, ss.str());
    }
    ROS_DEBUG("%s", ss.str().c_str());

    scene_node_->setVisible( false );
    return;
  }
  else
  {
    scene_node_->setVisible( true );
  }

  if (!manual_object_)
  {
    static uint32_t count = 0;
    std::stringstream ss;
    ss << "Triangle List Marker" << count++;
    manual_object_ = vis_manager_->getSceneManager()->createManualObject(ss.str());
    scene_node_->attachObject(manual_object_);

    ss << "Material";
    material_name_ = ss.str();
    material_ = Ogre::MaterialManager::getSingleton().create( material_name_, ROS_PACKAGE_NAME );
    material_->setReceiveShadows(false);
    material_->getTechnique(0)->setLightingEnabled(true);
    material_->setCullingMode(Ogre::CULL_NONE);

    vis_manager_->getSelectionManager()->removeObject(coll_);

    SelectionManager* sel_man = vis_manager_->getSelectionManager();
    coll_ = sel_man->createHandle();
    sel_man->addPickTechnique(coll_, material_);
    sel_man->addObject( coll_, SelectionHandlerPtr(new MarkerSelectionHandler(this, MarkerID(new_message->ns, new_message->id))) );
  }

  Ogre::Vector3 pos, scale;
  Ogre::Quaternion orient;
  transform(new_message, pos, orient, scale);

  if ( owner_ &&  (new_message->scale.x * new_message->scale.y * new_message->scale.z == 0.0f) )
  {
    owner_->setMarkerStatus(getID(), status_levels::Warn, "Scale of 0 in one of x/y/z");
  }

  setPosition(pos);
  setOrientation(orient);
  scene_node_->setScale(scale);

  // If we have the same number of tris as previously, just update the object
  if (old_message && num_points == old_message->points.size())
  {
    manual_object_->beginUpdate(0);
  }
  else // Otherwise clear it and begin anew
  {
    manual_object_->clear();
    manual_object_->estimateVertexCount(num_points);
    manual_object_->begin(material_name_, Ogre::RenderOperation::OT_TRIANGLE_LIST);
  }

  bool has_vertex_colors = new_message->colors.size() == num_points;

  if (has_vertex_colors)
  {
    for (size_t i = 0; i < num_points; ++i)
    {
      manual_object_->position(new_message->points[i].x, new_message->points[i].y, new_message->points[i].z);
      manual_object_->colour(new_message->colors[i].r, new_message->colors[i].g, new_message->colors[i].b, new_message->color.a);
    }
  }
  else
  {
    for (size_t i = 0; i < num_points; ++i)
    {
      manual_object_->position(new_message->points[i].x, new_message->points[i].y, new_message->points[i].z);
    }
  }

  manual_object_->end();

  if (has_vertex_colors)
  {
    material_->getTechnique(0)->setLightingEnabled(false);
  }
  else
  {
    material_->getTechnique(0)->setLightingEnabled(true);
    float r,g,b,a;
    r = new_message->color.r;
    g = new_message->color.g;
    b = new_message->color.b;
    a = new_message->color.a;
    material_->getTechnique(0)->setAmbient( r,g,b );
    material_->getTechnique(0)->setDiffuse( 0,0,0,a );
  }

  if ( new_message->color.a < 0.9998 )
  {
    material_->getTechnique(0)->setSceneBlending( Ogre::SBT_TRANSPARENT_ALPHA );
    material_->getTechnique(0)->setDepthWriteEnabled( false );
  }
  else
  {
    material_->getTechnique(0)->setSceneBlending( Ogre::SBT_REPLACE );
    material_->getTechnique(0)->setDepthWriteEnabled( true );
  }
}

S_MaterialPtr TriangleListMarker::getMaterials()
{
  S_MaterialPtr materials;
  materials.insert( material_ );
  return materials;
}

}

<|endoftext|>


<commit_before>#include <stan/math/error_handling/check_greater.hpp>
#include <gtest/gtest.h>
#include <stan/math/matrix/Eigen.hpp>

using stan::math::check_greater;

TEST(MathErrorHandling,CheckGreater) {
  const char* function = "check_greater(%1%)";
  double x = 10.0;
  double lb = 0.0;
  double result;

  EXPECT_TRUE(check_greater(function, x, lb, "x", &result))
    << "check_greater should be true with x > lb";

  x = -1.0;
  EXPECT_THROW(check_greater(function, x, lb, "x", &result), std::domain_error)
    << "check_greater should throw an exception with x < lb";

  x = lb;
  EXPECT_THROW(check_greater(function, x, lb, "x", &result), std::domain_error)
    << "check_greater should throw an exception with x == lb";

  x = std::numeric_limits<double>::infinity();
  EXPECT_TRUE(check_greater(function, x, lb, "x", &result))
    << "check_greater should be true with x == Inf and lb = 0.0";

  x = 10.0;
  lb = std::numeric_limits<double>::infinity();
  EXPECT_THROW(check_greater(function, x, lb, "x", &result), std::domain_error)
    << "check_greater should throw an exception with x == 10.0 and lb == Inf";

  x = std::numeric_limits<double>::infinity();
  lb = std::numeric_limits<double>::infinity();
  EXPECT_THROW(check_greater(function, x, lb, "x", &result), std::domain_error)
    << "check_greater should throw an exception with x == Inf and lb == Inf";
}

TEST(MathErrorHandling,CheckGreater_Matrix) {
  const char* function = "check_greater(%1%)";
  double result;
  double x;
  double low;
  Eigen::Matrix<double,Eigen::Dynamic,1> x_vec;
  Eigen::Matrix<double,Eigen::Dynamic,1> low_vec;
  x_vec.resize(3);
  low_vec.resize(3);

  // x_vec, low_vec
  result = 0;
  x_vec   << -1, 0, 1;
  low_vec << -2, -1, 0;
  EXPECT_TRUE(check_greater(function, x_vec, low_vec, "x", &result))
    << "check_greater: matrix<3,1>, matrix<3,1>";

  x_vec   <<   -1,    0,   1;
  low_vec << -1.1, -0.1, 0.9;
  EXPECT_TRUE(check_greater(function, x_vec, low_vec, "x", &result))
    << "check_greater: matrix<3,1>, matrix<3,1>";

  x_vec   << -1, 0, std::numeric_limits<double>::infinity();
  low_vec << -2, -1, 0;
  EXPECT_TRUE(check_greater(function, x_vec, low_vec, "x", &result))
    << "check_greater: matrix<3,1>, matrix<3,1>, y has infinity";

  x_vec   << -1, 0, 1;
  low_vec << -2, 0, 0;
  EXPECT_THROW(check_greater(function, x_vec, low_vec, "x", &result), std::domain_error)
    << "check_greater: matrix<3,1>, matrix<3,1>, should fail for index 1";

  x_vec   << -1, 0,  1;
  low_vec << -2, -1, std::numeric_limits<double>::infinity();
  EXPECT_THROW(check_greater(function, x_vec, low_vec, "x", &result), std::domain_error)
    << "check_greater: matrix<3,1>, matrix<3,1>, should fail with infinity";

  x_vec   << -1, 0,  std::numeric_limits<double>::infinity();
  low_vec << -2, -1, std::numeric_limits<double>::infinity();
  EXPECT_THROW(check_greater(function, x_vec, low_vec, "x", &result), std::domain_error)
    << "check_greater: matrix<3,1>, matrix<3,1>, should fail with infinity";

  x_vec   << -1, 0,  1;
  low_vec << -2, -1, -std::numeric_limits<double>::infinity();
  EXPECT_TRUE(check_greater(function, x_vec, low_vec, "x", &result))
  << "check_greater: matrix<3,1>, matrix<3,1>, should pass with -infinity";

  // x_vec, low
  result = 0;
  x_vec   << -1, 0, 1;
  low = -2;
  EXPECT_TRUE(check_greater(function, x_vec, low, "x", &result))
    << "check_greater: matrix<3,1>, double";

  x_vec   <<   -1,    0,   1;
  low = -std::numeric_limits<double>::infinity();
  EXPECT_TRUE(check_greater(function, x_vec, low, "x", &result))
    << "check_greater: matrix<3,1>, double";

  x_vec   << -1, 0, 1;
  low = 0;
  EXPECT_THROW(check_greater(function, x_vec, low, "x", &result), std::domain_error)
    << "check_greater: matrix<3,1>, double, should fail for index 1/2";

  x_vec   << -1, 0,  1;
  low = std::numeric_limits<double>::infinity();
  EXPECT_THROW(check_greater(function, x, low, "x", &result), std::domain_error)
    << "check_greater: matrix<3,1>, double, should fail with infinity";

  // x, low_vec
  result = 0;
  x = 2;
  low_vec << -1, 0, 1;
  EXPECT_TRUE(check_greater(function, x, low_vec, "x", &result))
    << "check_greater: double, matrix<3,1>";

  x = 10;
  low_vec << -1, 0, -std::numeric_limits<double>::infinity();
  EXPECT_TRUE(check_greater(function, x, low_vec, "x", &result))
    << "check_greater: double, matrix<3,1>, low has -inf";

  x = 10;
  low_vec << -1, 0, std::numeric_limits<double>::infinity();
  EXPECT_THROW(check_greater(function, x, low_vec, "x", &result), std::domain_error)
    << "check_greater: double, matrix<3,1>, low has inf";

  x = std::numeric_limits<double>::infinity();
  low_vec << -1, 0, std::numeric_limits<double>::infinity();
  EXPECT_THROW(check_greater(function, x, low_vec, "x", &result), std::domain_error)
    << "check_greater: double, matrix<3,1>, x is inf, low has inf";

  x = std::numeric_limits<double>::infinity();
  low_vec << -1, 0, 1;
  EXPECT_TRUE(check_greater(function, x, low_vec, "x", &result))
    << "check_greater: double, matrix<3,1>, x is inf";

  x = 1.1;
  low_vec << -1, 0, 1;
  EXPECT_TRUE(check_greater(function, x, low_vec, "x", &result))
    << "check_greater: double, matrix<3,1>";

  x = 0.9;
  low_vec << -1, 0, 1;
  EXPECT_THROW(check_greater(function, x, low_vec, "x", &result), std::domain_error)
    << "check_greater: double, matrix<3,1>";
}

TEST(MathErrorHandling,CheckGreater_Matrix_one_indexed_message) {
  const char* function = "check_greater(%1%)";
  double result;
  double x;
  double low;
  Eigen::Matrix<double,Eigen::Dynamic,1> x_vec;
  Eigen::Matrix<double,Eigen::Dynamic,1> low_vec;
  x_vec.resize(3);
  low_vec.resize(3);
  std::string message;

  // x_vec, low
  result = 0;
  x_vec << 10, 10, -1;
  low = 0;

  try {
    check_greater(function, x_vec, low, "x", &result);
    FAIL() << "should have thrown";
  } catch (std::domain_error& e) {
    message = e.what();
  } catch (...) {
    FAIL() << "threw the wrong error";
  }

  EXPECT_NE(std::string::npos, message.find("[3]"))
    << message;

  // x_vec, low_vec
  result = 0;
  x_vec << 10, -1, 10;
  low_vec << 0, 0, 0;

  try {
    check_greater(function, x_vec, low_vec, "x", &result);
    FAIL() << "should have thrown";
  } catch (std::domain_error& e) {
    message = e.what();
  } catch (...) {
    FAIL() << "threw the wrong error";
  }

  EXPECT_NE(std::string::npos, message.find("[2]"))
    << message;

  // x, low_vec
  result = 0;
  x = 0;
  low_vec << -1, 10, 10;

  try {
    check_greater(function, x, low_vec, "x", &result);
    FAIL() << "should have thrown";
  } catch (std::domain_error& e) {
    message = e.what();
  } catch (...) {
    FAIL() << "threw the wrong error";
  }

  EXPECT_EQ(std::string::npos, message.find("["))
    << "no index provided" << std::endl
    << message;
}
<commit_msg>added NaN test for check_greater<commit_after>#include <stan/math/error_handling/check_greater.hpp>
#include <gtest/gtest.h>
#include <stan/math/matrix/Eigen.hpp>

using stan::math::check_greater;

TEST(MathErrorHandling,CheckGreater) {
  const char* function = "check_greater(%1%)";
  double x = 10.0;
  double lb = 0.0;
  double result;

  EXPECT_TRUE(check_greater(function, x, lb, "x", &result))
    << "check_greater should be true with x > lb";

  x = -1.0;
  EXPECT_THROW(check_greater(function, x, lb, "x", &result), std::domain_error)
    << "check_greater should throw an exception with x < lb";

  x = lb;
  EXPECT_THROW(check_greater(function, x, lb, "x", &result), std::domain_error)
    << "check_greater should throw an exception with x == lb";

  x = std::numeric_limits<double>::infinity();
  EXPECT_TRUE(check_greater(function, x, lb, "x", &result))
    << "check_greater should be true with x == Inf and lb = 0.0";

  x = 10.0;
  lb = std::numeric_limits<double>::infinity();
  EXPECT_THROW(check_greater(function, x, lb, "x", &result), std::domain_error)
    << "check_greater should throw an exception with x == 10.0 and lb == Inf";

  x = std::numeric_limits<double>::infinity();
  lb = std::numeric_limits<double>::infinity();
  EXPECT_THROW(check_greater(function, x, lb, "x", &result), std::domain_error)
    << "check_greater should throw an exception with x == Inf and lb == Inf";
}

TEST(MathErrorHandling,CheckGreater_Matrix) {
  const char* function = "check_greater(%1%)";
  double result;
  double x;
  double low;
  Eigen::Matrix<double,Eigen::Dynamic,1> x_vec;
  Eigen::Matrix<double,Eigen::Dynamic,1> low_vec;
  x_vec.resize(3);
  low_vec.resize(3);

  // x_vec, low_vec
  result = 0;
  x_vec   << -1, 0, 1;
  low_vec << -2, -1, 0;
  EXPECT_TRUE(check_greater(function, x_vec, low_vec, "x", &result))
    << "check_greater: matrix<3,1>, matrix<3,1>";

  x_vec   <<   -1,    0,   1;
  low_vec << -1.1, -0.1, 0.9;
  EXPECT_TRUE(check_greater(function, x_vec, low_vec, "x", &result))
    << "check_greater: matrix<3,1>, matrix<3,1>";

  x_vec   << -1, 0, std::numeric_limits<double>::infinity();
  low_vec << -2, -1, 0;
  EXPECT_TRUE(check_greater(function, x_vec, low_vec, "x", &result))
    << "check_greater: matrix<3,1>, matrix<3,1>, y has infinity";

  x_vec   << -1, 0, 1;
  low_vec << -2, 0, 0;
  EXPECT_THROW(check_greater(function, x_vec, low_vec, "x", &result), std::domain_error)
    << "check_greater: matrix<3,1>, matrix<3,1>, should fail for index 1";

  x_vec   << -1, 0,  1;
  low_vec << -2, -1, std::numeric_limits<double>::infinity();
  EXPECT_THROW(check_greater(function, x_vec, low_vec, "x", &result), std::domain_error)
    << "check_greater: matrix<3,1>, matrix<3,1>, should fail with infinity";

  x_vec   << -1, 0,  std::numeric_limits<double>::infinity();
  low_vec << -2, -1, std::numeric_limits<double>::infinity();
  EXPECT_THROW(check_greater(function, x_vec, low_vec, "x", &result), std::domain_error)
    << "check_greater: matrix<3,1>, matrix<3,1>, should fail with infinity";

  x_vec   << -1, 0,  1;
  low_vec << -2, -1, -std::numeric_limits<double>::infinity();
  EXPECT_TRUE(check_greater(function, x_vec, low_vec, "x", &result))
  << "check_greater: matrix<3,1>, matrix<3,1>, should pass with -infinity";

  // x_vec, low
  result = 0;
  x_vec   << -1, 0, 1;
  low = -2;
  EXPECT_TRUE(check_greater(function, x_vec, low, "x", &result))
    << "check_greater: matrix<3,1>, double";

  x_vec   <<   -1,    0,   1;
  low = -std::numeric_limits<double>::infinity();
  EXPECT_TRUE(check_greater(function, x_vec, low, "x", &result))
    << "check_greater: matrix<3,1>, double";

  x_vec   << -1, 0, 1;
  low = 0;
  EXPECT_THROW(check_greater(function, x_vec, low, "x", &result), std::domain_error)
    << "check_greater: matrix<3,1>, double, should fail for index 1/2";

  x_vec   << -1, 0,  1;
  low = std::numeric_limits<double>::infinity();
  EXPECT_THROW(check_greater(function, x, low, "x", &result), std::domain_error)
    << "check_greater: matrix<3,1>, double, should fail with infinity";

  // x, low_vec
  result = 0;
  x = 2;
  low_vec << -1, 0, 1;
  EXPECT_TRUE(check_greater(function, x, low_vec, "x", &result))
    << "check_greater: double, matrix<3,1>";

  x = 10;
  low_vec << -1, 0, -std::numeric_limits<double>::infinity();
  EXPECT_TRUE(check_greater(function, x, low_vec, "x", &result))
    << "check_greater: double, matrix<3,1>, low has -inf";

  x = 10;
  low_vec << -1, 0, std::numeric_limits<double>::infinity();
  EXPECT_THROW(check_greater(function, x, low_vec, "x", &result), std::domain_error)
    << "check_greater: double, matrix<3,1>, low has inf";

  x = std::numeric_limits<double>::infinity();
  low_vec << -1, 0, std::numeric_limits<double>::infinity();
  EXPECT_THROW(check_greater(function, x, low_vec, "x", &result), std::domain_error)
    << "check_greater: double, matrix<3,1>, x is inf, low has inf";

  x = std::numeric_limits<double>::infinity();
  low_vec << -1, 0, 1;
  EXPECT_TRUE(check_greater(function, x, low_vec, "x", &result))
    << "check_greater: double, matrix<3,1>, x is inf";

  x = 1.1;
  low_vec << -1, 0, 1;
  EXPECT_TRUE(check_greater(function, x, low_vec, "x", &result))
    << "check_greater: double, matrix<3,1>";

  x = 0.9;
  low_vec << -1, 0, 1;
  EXPECT_THROW(check_greater(function, x, low_vec, "x", &result), std::domain_error)
    << "check_greater: double, matrix<3,1>";
}

TEST(MathErrorHandling,CheckGreater_Matrix_one_indexed_message) {
  const char* function = "check_greater(%1%)";
  double result;
  double x;
  double low;
  Eigen::Matrix<double,Eigen::Dynamic,1> x_vec;
  Eigen::Matrix<double,Eigen::Dynamic,1> low_vec;
  x_vec.resize(3);
  low_vec.resize(3);
  std::string message;

  // x_vec, low
  result = 0;
  x_vec << 10, 10, -1;
  low = 0;

  try {
    check_greater(function, x_vec, low, "x", &result);
    FAIL() << "should have thrown";
  } catch (std::domain_error& e) {
    message = e.what();
  } catch (...) {
    FAIL() << "threw the wrong error";
  }

  EXPECT_NE(std::string::npos, message.find("[3]"))
    << message;

  // x_vec, low_vec
  result = 0;
  x_vec << 10, -1, 10;
  low_vec << 0, 0, 0;

  try {
    check_greater(function, x_vec, low_vec, "x", &result);
    FAIL() << "should have thrown";
  } catch (std::domain_error& e) {
    message = e.what();
  } catch (...) {
    FAIL() << "threw the wrong error";
  }

  EXPECT_NE(std::string::npos, message.find("[2]"))
    << message;

  // x, low_vec
  result = 0;
  x = 0;
  low_vec << -1, 10, 10;

  try {
    check_greater(function, x, low_vec, "x", &result);
    FAIL() << "should have thrown";
  } catch (std::domain_error& e) {
    message = e.what();
  } catch (...) {
    FAIL() << "threw the wrong error";
  }

  EXPECT_EQ(std::string::npos, message.find("["))
    << "no index provided" << std::endl
    << message;
}

TEST(MathErrorHandling,CheckGreater_nan) {
  const char* function = "check_greater(%1%)";
  double x = 10.0;
  double lb = 0.0;
  double result;
  double nan = std::numeric_limits<double>::quiet_NaN();

  EXPECT_THROW(check_greater(function, nan, lb, "x", &result),
               std::domain_error);
  EXPECT_THROW(check_greater(function, x, nan, "x", &result),
               std::domain_error);
  EXPECT_THROW(check_greater(function, nan, nan, "x", &result),
               std::domain_error);

  Eigen::Matrix<double,Eigen::Dynamic,1> x_vec(3);
  Eigen::Matrix<double,Eigen::Dynamic,1> low_vec(3);

  // x_vec, low_vec
  x_vec   << -1, 0, 1;
  low_vec << -2, -1, 0;
  EXPECT_THROW(check_greater(function, x_vec, nan, "x", &result),
               std::domain_error);

  for (int i = 0; i < x_vec.size(); i++) {
    x_vec   << -1, 0, 1;
    x_vec(i) = nan;
    EXPECT_THROW(check_greater(function, x_vec, low_vec, "x", &result),
                 std::domain_error);
  }

  x_vec   << -1, 0, 1;
  for (int i = 0; i < low_vec.size(); i++) {
    low_vec   << -1, 0, 1;
    low_vec(i) = nan;
    EXPECT_THROW(check_greater(function, x_vec, low_vec, "x", &result),
                 std::domain_error);
  }

  for (int i = 0; i < x_vec.size(); i++) {
    x_vec   << -1, 0, 1;
    low_vec << -2, -1, 0;
    x_vec(i) = nan;
    for (int j = 0; j < low_vec.size(); j++) {
      low_vec(i) = nan;
      EXPECT_THROW(check_greater(function, x_vec, low_vec, "x", &result),
                   std::domain_error);
    }
  }
}

<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <map>
#include <ostream>
#include <string>

#include <process/future.hpp>
#include <process/gtest.hpp>
#include <process/owned.hpp>

#include <stout/gtest.hpp>
#include <stout/option.hpp>
#include <stout/path.hpp>
#include <stout/strings.hpp>

#include "common/parse.hpp"

#include "tests/cluster.hpp"
#include "tests/mesos.hpp"

#include "slave/containerizer/mesos/containerizer.hpp"

#include "tests/containerizer/docker_archive.hpp"

using process::Future;
using process::Owned;

using std::map;
using std::ostream;
using std::string;

using mesos::internal::slave::Containerizer;
using mesos::internal::slave::Fetcher;
using mesos::internal::slave::MesosContainerizer;

using mesos::slave::ContainerTermination;

namespace mesos {
namespace internal {
namespace tests {

struct DevicesTestParam
{
  DevicesTestParam(
      const string& _containerCheck,
      const string& _allowedDevices)
    : containerCheck(_containerCheck),
      allowedDevices(_allowedDevices) {}

  const string containerCheck;
  const string allowedDevices;
};

ostream& operator<<(ostream& stream, const DevicesTestParam& param)
{
  return stream << param.containerCheck;
}

class LinuxDevicesIsolatorTest
  : public MesosTest,
    public ::testing::WithParamInterface<DevicesTestParam>
{
public:
  LinuxDevicesIsolatorTest()
    : param(GetParam()) {}

  DevicesTestParam param;
};

TEST_P(LinuxDevicesIsolatorTest, ROOT_PopulateWhitelistedDevices)
{
  // Verify that all the necessary devices are present on the host.
  // All reasonable Linux configuration should have these devices.
  ASSERT_TRUE(os::exists("/dev/kmsg"));
  ASSERT_TRUE(os::exists("/dev/loop-control"));

  slave::Flags flags = CreateSlaveFlags();

  flags.isolation = "linux/devices,filesystem/linux,docker/runtime";
  flags.docker_registry =  path::join(sandbox.get(), "registry");
  flags.docker_store_dir = path::join(sandbox.get(), "store");
  flags.image_providers = "docker";

  flags.allowed_devices =
    flags::parse<DeviceWhitelist>(param.allowedDevices).get();

  AWAIT_READY(DockerArchive::create(flags.docker_registry, "test_image"));

  Fetcher fetcher(flags);

  Try<MesosContainerizer*> create =
    MesosContainerizer::create(flags, true, &fetcher);

  ASSERT_SOME(create);

  Owned<Containerizer> containerizer(create.get());

  ContainerID containerId;
  containerId.set_value(id::UUID::random().toString());

  ExecutorInfo executor = createExecutorInfo(
      "test_executor",
      strings::join(";", "ls -l /dev", param.containerCheck));

  executor.mutable_container()->CopyFrom(createContainerInfo("test_image"));

  string directory = path::join(flags.work_dir, "sandbox");
  ASSERT_SOME(os::mkdir(directory));

  // Launch the container check command as the non-root user. All the
  // check commands are testing for device file access, but root will
  // always have access.
  Future<Containerizer::LaunchResult> launch = containerizer->launch(
      containerId,
      createContainerConfig(
          None(), executor, directory, os::getenv("SUDO_USER").get()),
      map<string, string>(),
      None());

  AWAIT_ASSERT_EQ(Containerizer::LaunchResult::SUCCESS, launch);

  Future<Option<ContainerTermination>> wait = containerizer->wait(containerId);

  AWAIT_READY(wait);
  ASSERT_SOME(wait.get());
  ASSERT_TRUE(wait->get().has_status());
  EXPECT_WEXITSTATUS_EQ(0, wait->get().status());
}

INSTANTIATE_TEST_CASE_P(
  DevicesTestParam,
  LinuxDevicesIsolatorTest,
  ::testing::Values(
    // Test that /dev/loop-control is a character device and that
    // /dev/kmsg doesn't exist. The latter test ensures that we
    // won't succeed by accidentally running on the host.
    DevicesTestParam(
      "test -c /dev/loop-control && test ! -e /dev/kmsg",
      R"~({
        "allowed_devices": [
          {
            "device": {
              "path": "/dev/loop-control"
            },
            "access": {}
          }
        ]
      })~"),
    // Test that a device in a subdirectory is populated.
    DevicesTestParam(
      "test -r /dev/cpu/0/cpuid",
      R"~({
        "allowed_devices": [
          {
            "device": {
              "path": "/dev/cpu/0/cpuid"
            },
            "access": {
              "read": true
            }
          }
        ]
      })~"),
    // Test that read-only devices are populated in read-only mode.
    DevicesTestParam(
      "test -r /dev/loop-control && test ! -w /dev/loop-control",
      R"~({
        "allowed_devices": [
          {
            "device": {
              "path": "/dev/loop-control"
            },
            "access": {
              "read": true
            }
          }
        ]
      })~"),
    // Test that write-only devices are populated in write-only mode.
    DevicesTestParam(
      "test -w /dev/loop-control && test ! -r /dev/loop-control",
      R"~({
        "allowed_devices": [
          {
            "device": {
              "path": "/dev/loop-control"
            },
            "access": {
              "write": true
            }
          }
        ]
      })~"),
    // Test that read-write devices are populated in read-write mode.
    DevicesTestParam(
      "test -w /dev/loop-control && test -r /dev/loop-control",
      R"~({
        "allowed_devices": [
          {
            "device": {
              "path": "/dev/loop-control"
            },
            "access": {
              "read": true,
              "write": true
            }
          }
        ]
      })~")));

} // namespace tests {
} // namespace internal {
} // namespace mesos {
<commit_msg>Updated `linux/devices` isolator tests for compiler compatibility.<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <map>
#include <ostream>
#include <string>

#include <process/future.hpp>
#include <process/gtest.hpp>
#include <process/owned.hpp>

#include <stout/gtest.hpp>
#include <stout/option.hpp>
#include <stout/path.hpp>
#include <stout/strings.hpp>

#include "common/parse.hpp"

#include "tests/cluster.hpp"
#include "tests/mesos.hpp"

#include "slave/containerizer/mesos/containerizer.hpp"

#include "tests/containerizer/docker_archive.hpp"

using process::Future;
using process::Owned;

using std::map;
using std::ostream;
using std::string;

using mesos::internal::slave::Containerizer;
using mesos::internal::slave::Fetcher;
using mesos::internal::slave::MesosContainerizer;

using mesos::slave::ContainerTermination;

namespace mesos {
namespace internal {
namespace tests {

struct DevicesTestParam
{
  const string containerCheck;
  const string allowedDevices;
};

ostream& operator<<(ostream& stream, const DevicesTestParam& param)
{
  return stream << param.containerCheck;
}

class LinuxDevicesIsolatorTest
  : public MesosTest,
    public ::testing::WithParamInterface<DevicesTestParam>
{
public:
  LinuxDevicesIsolatorTest()
    : param(GetParam()) {}

  DevicesTestParam param;
};

TEST_P(LinuxDevicesIsolatorTest,
       ROOT_UNPRIVILEGED_USER_PopulateWhitelistedDevices)
{
  // Verify that all the necessary devices are present on the host.
  // All reasonable Linux configuration should have these devices.
  ASSERT_TRUE(os::exists("/dev/kmsg"));
  ASSERT_TRUE(os::exists("/dev/loop-control"));

  slave::Flags flags = CreateSlaveFlags();

  flags.isolation = "linux/devices,filesystem/linux,docker/runtime";
  flags.docker_registry =  path::join(sandbox.get(), "registry");
  flags.docker_store_dir = path::join(sandbox.get(), "store");
  flags.image_providers = "docker";

  flags.allowed_devices =
    flags::parse<DeviceWhitelist>(param.allowedDevices).get();

  AWAIT_READY(DockerArchive::create(flags.docker_registry, "test_image"));

  Fetcher fetcher(flags);

  Try<MesosContainerizer*> create =
    MesosContainerizer::create(flags, true, &fetcher);

  ASSERT_SOME(create);

  Owned<Containerizer> containerizer(create.get());

  ContainerID containerId;
  containerId.set_value(id::UUID::random().toString());

  ExecutorInfo executor = createExecutorInfo(
      "test_executor",
      strings::join(";", "ls -l /dev", param.containerCheck));

  executor.mutable_container()->CopyFrom(createContainerInfo("test_image"));

  string directory = path::join(flags.work_dir, "sandbox");
  ASSERT_SOME(os::mkdir(directory));

  // Launch the container check command as the non-root user. All the
  // check commands are testing for device file access, but root will
  // always have access.
  Future<Containerizer::LaunchResult> launch = containerizer->launch(
      containerId,
      createContainerConfig(
          None(), executor, directory, os::getenv("SUDO_USER").get()),
      map<string, string>(),
      None());

  AWAIT_ASSERT_EQ(Containerizer::LaunchResult::SUCCESS, launch);

  Future<Option<ContainerTermination>> wait = containerizer->wait(containerId);

  AWAIT_READY(wait);
  ASSERT_SOME(wait.get());
  ASSERT_TRUE(wait->get().has_status());
  EXPECT_WEXITSTATUS_EQ(0, wait->get().status());
}

static const std::vector<DevicesTestParam> devicesTestValues {
  // Test that /dev/loop-control is a character device and that
  // /dev/kmsg doesn't exist. The latter test ensures that we
  // won't succeed by accidentally running on the host.
  DevicesTestParam{
    "test -c /dev/loop-control && test ! -e /dev/kmsg",
    R"~({
      "allowed_devices": [
        {
          "device": {
            "path": "/dev/loop-control"
          },
          "access": {}
        }
      ]
    })~"},
  // Test that a device in a subdirectory is populated.
  DevicesTestParam{
    "test -r /dev/cpu/0/cpuid",
    R"~({
      "allowed_devices": [
        {
          "device": {
            "path": "/dev/cpu/0/cpuid"
          },
          "access": {
            "read": true
          }
        }
      ]
    })~"},
  // Test that read-only devices are populated in read-only mode.
  DevicesTestParam{
    "test -r /dev/loop-control && test ! -w /dev/loop-control",
    R"~({
      "allowed_devices": [
        {
          "device": {
            "path": "/dev/loop-control"
          },
          "access": {
            "read": true
          }
        }
      ]
    })~"},
  // Test that write-only devices are populated in write-only mode.
  DevicesTestParam{
    "test -w /dev/loop-control && test ! -r /dev/loop-control",
    R"~({
      "allowed_devices": [
        {
          "device": {
            "path": "/dev/loop-control"
          },
          "access": {
            "write": true
          }
        }
      ]
    })~"},
  // Test that read-write devices are populated in read-write mode.
  DevicesTestParam{
    "test -w /dev/loop-control && test -r /dev/loop-control",
    R"~({
      "allowed_devices": [
        {
          "device": {
            "path": "/dev/loop-control"
          },
          "access": {
            "read": true,
            "write": true
          }
        }
      ]
    })~"}
};

INSTANTIATE_TEST_CASE_P(
  DevicesTestParam,
  LinuxDevicesIsolatorTest,
  ::testing::ValuesIn(devicesTestValues));

} // namespace tests {
} // namespace internal {
} // namespace mesos {
<|endoftext|>


<commit_before>#include "artworkfilter_tests.h"
#include "Mocks/artworkmetadatamock.h"
#include "../../xpiks-qt/Helpers/filterhelpers.h"
#include "../../xpiks-qt/Common/flags.h"

void ArtworkFilterTests::searchImageVectorTest() {
    Mocks::ArtworkMetadataMock metadata("/path/to/file.jpg");
    QVERIFY(Helpers::containsPartsSearch("x:image", &metadata, false));
    QVERIFY(!Helpers::containsPartsSearch("x:vector", &metadata, false));

    metadata.attachVector("/path/to/file.eps");
    QVERIFY(!Helpers::containsPartsSearch("x:image", &metadata, false));
    QVERIFY(Helpers::containsPartsSearch("x:vector", &metadata, false));
}

void ArtworkFilterTests::searchByKeywordsTest() {
    Mocks::ArtworkMetadataMock metadata("/path/to/file.jpg");
    metadata.setKeywords(QStringList() << "keyword" << "another" << "test");
    QVERIFY(Helpers::containsPartsSearch("keyw TSTS", &metadata, false));
    QVERIFY(!Helpers::containsPartsSearch("!keyw", &metadata, false));
    QVERIFY(Helpers::containsPartsSearch("!keyword", &metadata, false));

    QVERIFY(Helpers::containsPartsSearch("keyword super", &metadata, false));
    QVERIFY(!Helpers::containsPartsSearch("keyword super", &metadata, true));
}

void ArtworkFilterTests::searchByTitleTest() {
    Mocks::ArtworkMetadataMock metadata("/path/to/file.jpg");
    metadata.setTitle("my long title here");
    QVERIFY(Helpers::containsPartsSearch("tit", &metadata, false));
    QVERIFY(!Helpers::containsPartsSearch("!tit", &metadata, false));
    // strict search works only for keywords
    QVERIFY(!Helpers::containsPartsSearch("!title", &metadata, false));

    QVERIFY(!Helpers::containsPartsSearch("keyword super", &metadata, false));
    QVERIFY(Helpers::containsPartsSearch("here my", &metadata, true));
}

void ArtworkFilterTests::searchByDescriptionTest() {
    Mocks::ArtworkMetadataMock metadata("/path/to/file.jpg");
    metadata.setDescription("my long desciption john");
    QVERIFY(Helpers::containsPartsSearch("o", &metadata, false));
    QVERIFY(!Helpers::containsPartsSearch("!o", &metadata, false));
    // strict search works only for keywords
    QVERIFY(!Helpers::containsPartsSearch("!description", &metadata, false));

    QVERIFY(!Helpers::containsPartsSearch("myjohn", &metadata, false));
    QVERIFY(!Helpers::containsPartsSearch("descriptionmy", &metadata, true));
}

void ArtworkFilterTests::strictSearchTest() {
    Mocks::ArtworkMetadataMock metadata("/path/to/file.jpg");
    metadata.setKeywords(QStringList() << "keyword" << "ano!ther" << "test" << "k");
    QVERIFY(Helpers::containsPartsSearch("keyw", &metadata, false));
    QVERIFY(!Helpers::containsPartsSearch("!keyw", &metadata, false));
    QVERIFY(Helpers::containsPartsSearch("!keyword", &metadata, false));

    QVERIFY(!Helpers::containsPartsSearch("!!", &metadata, false));
    QVERIFY(Helpers::containsPartsSearch("!k", &metadata, true));

    metadata.appendKeyword("!");
    QVERIFY(Helpers::containsPartsSearch("!", &metadata, false));
}

void ArtworkFilterTests::caseSensitiveKeywordSearchTest() {
    Mocks::ArtworkMetadataMock metadata("/path/to/file.jpg");
    metadata.setKeywords(QStringList() << "keYwOrd" << "keYword");

    int flags = Common::SearchFlagSearchKeywords | Common::SearchFlagCaseSensitive;

    QVERIFY(Helpers::hasSearchMatch("YwO", &metadata, flags));
    QVERIFY(!Helpers::hasSearchMatch("ywO", &metadata, flags));
}

void ArtworkFilterTests::cantFindWithFilterDescriptionTest() {
    Mocks::ArtworkMetadataMock metadata("/path/to/file.jpg");
    metadata.setDescription("token between here");
    metadata.setKeywords(QStringList() << "some keyword" << "another stuff");

    int flags = Common::SearchFlagSearchKeywords | Common::SearchFlagSearchTitle;

    QVERIFY(!Helpers::hasSearchMatch("between", &metadata, flags));
    QVERIFY(Helpers::hasSearchMatch("between", &metadata, flags | Common::SearchFlagSearchDescription));
}

void ArtworkFilterTests::cantFindWithFilterTitleTest() {
    Mocks::ArtworkMetadataMock metadata("/path/to/file.jpg");
    metadata.setTitle("token between here");
    metadata.setKeywords(QStringList() << "some keyword" << "another stuff");

    int flags = Common::SearchFlagSearchDescription | Common::SearchFlagSearchKeywords;

    QVERIFY(!Helpers::hasSearchMatch("between", &metadata, flags));
    QVERIFY(Helpers::hasSearchMatch("between", &metadata, flags | Common::SearchFlagSearchTitle));
}

void ArtworkFilterTests::cantFindWithFilterKeywordsTest() {
    Mocks::ArtworkMetadataMock metadata("/path/to/file.jpg");
    metadata.setDescription("another keyword in description");
    metadata.setTitle("token between here");
    metadata.setKeywords(QStringList() << "some keyword" << "another stuff");

    int flags = Common::SearchFlagSearchDescription | Common::SearchFlagSearchTitle;

    QVERIFY(!Helpers::hasSearchMatch("stuff", &metadata, flags));
    QVERIFY(Helpers::hasSearchMatch("stuff", &metadata, flags | Common::SearchFlagSearchKeywords));
}

void ArtworkFilterTests::cantFindWithFilterSpecialTest() {
    Mocks::ArtworkMetadataMock metadata("/path/to/file.jpg");
    metadata.setDescription("another keyword in description");
    metadata.setTitle("token between here");
    metadata.setKeywords(QStringList() << "some keyword" << "another stuff");

    int flags = Common::SearchFlagSearchDescription | Common::SearchFlagSearchTitle | Common::SearchFlagSearchKeywords;

    QVERIFY(!Helpers::hasSearchMatch("x:empty", &metadata, flags));
    QVERIFY(Helpers::hasSearchMatch("x:empty", &metadata, flags | Common::SearchFlagReservedTerms));
}
<commit_msg>Fix for tests<commit_after>#include "artworkfilter_tests.h"
#include "Mocks/artworkmetadatamock.h"
#include "../../xpiks-qt/Helpers/filterhelpers.h"
#include "../../xpiks-qt/Common/flags.h"

void ArtworkFilterTests::searchImageVectorTest() {
    Mocks::ArtworkMetadataMock metadata("/path/to/file.jpg");
    QVERIFY(Helpers::containsPartsSearch("x:image", &metadata, false));
    QVERIFY(!Helpers::containsPartsSearch("x:vector", &metadata, false));

    metadata.attachVector("/path/to/file.eps");
    QVERIFY(!Helpers::containsPartsSearch("x:image", &metadata, false));
    QVERIFY(Helpers::containsPartsSearch("x:vector", &metadata, false));
}

void ArtworkFilterTests::searchByKeywordsTest() {
    Mocks::ArtworkMetadataMock metadata("/path/to/file.jpg");
    metadata.setKeywords(QStringList() << "keyword" << "another" << "test");
    QVERIFY(Helpers::containsPartsSearch("keyw TSTS", &metadata, false));
    QVERIFY(!Helpers::containsPartsSearch("!keyw", &metadata, false));
    QVERIFY(Helpers::containsPartsSearch("!keyword", &metadata, false));

    QVERIFY(Helpers::containsPartsSearch("keyword super", &metadata, false));
    QVERIFY(!Helpers::containsPartsSearch("keyword super", &metadata, true));
}

void ArtworkFilterTests::searchByTitleTest() {
    Mocks::ArtworkMetadataMock metadata("/path/to/file.jpg");
    metadata.setTitle("my long title here");
    QVERIFY(Helpers::containsPartsSearch("tit", &metadata, false));
    QVERIFY(!Helpers::containsPartsSearch("!tit", &metadata, false));
    // strict search works only for keywords
    QVERIFY(!Helpers::containsPartsSearch("!title", &metadata, false));

    QVERIFY(!Helpers::containsPartsSearch("keyword super", &metadata, false));
    QVERIFY(Helpers::containsPartsSearch("here my", &metadata, true));
}

void ArtworkFilterTests::searchByDescriptionTest() {
    Mocks::ArtworkMetadataMock metadata("/path/to/file.jpg");
    metadata.setDescription("my long desciption john");
    QVERIFY(Helpers::containsPartsSearch("o", &metadata, false));
    QVERIFY(!Helpers::containsPartsSearch("!o", &metadata, false));
    // strict search works only for keywords
    QVERIFY(!Helpers::containsPartsSearch("!description", &metadata, false));

    QVERIFY(!Helpers::containsPartsSearch("myjohn", &metadata, false));
    QVERIFY(!Helpers::containsPartsSearch("descriptionmy", &metadata, true));
}

void ArtworkFilterTests::strictSearchTest() {
    Mocks::ArtworkMetadataMock metadata("/path/to/file.jpg");
    metadata.setKeywords(QStringList() << "keyword" << "ano!ther" << "test" << "k");
    QVERIFY(Helpers::containsPartsSearch("keyw", &metadata, false));
    QVERIFY(!Helpers::containsPartsSearch("!keyw", &metadata, false));
    QVERIFY(Helpers::containsPartsSearch("!keyword", &metadata, false));

    QVERIFY(!Helpers::containsPartsSearch("!!", &metadata, false));
    QVERIFY(Helpers::containsPartsSearch("!k", &metadata, true));

    metadata.appendKeyword("!");
    QVERIFY(Helpers::containsPartsSearch("!", &metadata, false));
}

void ArtworkFilterTests::caseSensitiveKeywordSearchTest() {
    Mocks::ArtworkMetadataMock metadata("/path/to/file.jpg");
    metadata.setKeywords(QStringList() << "keYwOrd" << "keYword");

    int flags = Common::SearchFlagSearchKeywords | Common::SearchFlagCaseSensitive;

    QVERIFY(Helpers::hasSearchMatch("YwO", &metadata, flags));
    QVERIFY(!Helpers::hasSearchMatch("ywO", &metadata, flags));
}

void ArtworkFilterTests::cantFindWithFilterDescriptionTest() {
    Mocks::ArtworkMetadataMock metadata("/path/to/file.jpg");
    metadata.setDescription("token between here");
    metadata.setKeywords(QStringList() << "some keyword" << "another stuff");

    int flags = Common::SearchFlagSearchKeywords | Common::SearchFlagSearchTitle;

    QVERIFY(!Helpers::hasSearchMatch("between", &metadata, flags));
    QVERIFY(Helpers::hasSearchMatch("between", &metadata, flags | Common::SearchFlagSearchDescription));
}

void ArtworkFilterTests::cantFindWithFilterTitleTest() {
    Mocks::ArtworkMetadataMock metadata("/path/to/file.jpg");
    metadata.setTitle("token between here");
    metadata.setKeywords(QStringList() << "some keyword" << "another stuff");

    int flags = Common::SearchFlagSearchDescription | Common::SearchFlagSearchKeywords;

    QVERIFY(!Helpers::hasSearchMatch("between", &metadata, flags));
    QVERIFY(Helpers::hasSearchMatch("between", &metadata, flags | Common::SearchFlagSearchTitle));
}

void ArtworkFilterTests::cantFindWithFilterKeywordsTest() {
    Mocks::ArtworkMetadataMock metadata("/path/to/file.jpg");
    metadata.setDescription("another keyword in description");
    metadata.setTitle("token between here");
    metadata.setKeywords(QStringList() << "some keyword" << "another stuff");

    int flags = Common::SearchFlagSearchDescription | Common::SearchFlagSearchTitle;

    QVERIFY(!Helpers::hasSearchMatch("stuff", &metadata, flags));
    QVERIFY(Helpers::hasSearchMatch("stuff", &metadata, flags | Common::SearchFlagSearchKeywords));
}

void ArtworkFilterTests::cantFindWithFilterSpecialTest() {
    Mocks::ArtworkMetadataMock metadata("/path/to/file.jpg");
    metadata.setDescription("another keyword in description");
    metadata.setTitle("token between here");
    metadata.setKeywords(QStringList() << "some keyword" << "another stuff");

    int flags = Common::SearchFlagSearchDescription | Common::SearchFlagSearchTitle | Common::SearchFlagSearchKeywords;

    QVERIFY(!Helpers::hasSearchMatch("x:modified", &metadata, flags));
    QVERIFY(Helpers::hasSearchMatch("x:modified", &metadata, flags | Common::SearchFlagReservedTerms));
}
<|endoftext|>