<commit_before>#include "diff_system.h"
#include "dof_map.h"
#include "numeric_vector.h"
#include "time_solver.h"

DifferentiableSystem::DifferentiableSystem
                      (EquationSystems& es,
                       const std::string& name,
                       const unsigned int number) :
  Parent      (es, name, number),
  compute_internal_sides(false),
  postprocess_sides(false),
  time_solver (NULL),
  time(0.),
  deltat(1.),
  print_solution_norms(false),
  print_residual_norms(false),
  print_residuals(false),
  print_jacobian_norms(false),
  print_jacobians(false),
  current_local_nonlinear_solution(NumericVector<Number>::build())
{
  untested();
}

DifferentiableSystem::~DifferentiableSystem ()
{
}

void DifferentiableSystem::reinit ()
{
  Parent::reinit();

  // Resize the serial nonlinear solution for the current mesh
  current_local_nonlinear_solution->init (this->n_dofs());

  time_solver->reinit();
}

void DifferentiableSystem::init_data ()
{
  // First, allocate a vector for the iterate in our quasi_Newton
  // solver

  // FIXME - there really ought to be a way to just use the System
  // solution vector if the solver doesn't need an extra vector!

  // We don't want to project more solutions than we have to
//  this->add_vector("_nonlinear_solution", false);
  this->add_vector("_nonlinear_solution");
//  this->project_solution_on_reinit() = false;

  // Next, give us flags for every variable that might be time
  // evolving
  _time_evolving.resize(this->n_vars(), false);

  // Do any initialization our solvers need
  assert (time_solver.get() != NULL);
  time_solver->init();

  // Next initialize ImplicitSystem data
  Parent::init_data();

  // Finally initialize solution/residual/jacobian data structures
  unsigned int n_vars = this->n_vars();

  dof_indices_var.resize(n_vars);

  elem_subsolutions.clear();
  elem_subsolutions.reserve(n_vars);
  elem_subresiduals.clear();
  elem_subresiduals.reserve(n_vars);
  elem_subjacobians.clear();
  elem_subjacobians.resize(n_vars);
  for (unsigned int i=0; i != n_vars; ++i)
    {
      elem_subsolutions.push_back(new DenseSubVector<Number>(elem_solution));
      elem_subresiduals.push_back(new DenseSubVector<Number>(elem_residual));
      elem_subjacobians[i].clear();
      elem_subjacobians[i].reserve(n_vars);

      for (unsigned int j=0; j != n_vars; ++j)
        {
          elem_subjacobians[i].push_back
            (new DenseSubMatrix<Number>(elem_jacobian));
        }
    }

  // Resize the serial nonlinear solution for the current mesh
  current_local_nonlinear_solution->init (this->n_dofs());
}

void DifferentiableSystem::assemble ()
{
  this->assembly(true, true);
}

void DifferentiableSystem::solve ()
{
  time_solver->solve();
}

Number DifferentiableSystem::current_nonlinear_solution (const unsigned int global_dof_number) const
{
  // Check the sizes
  assert (global_dof_number < this->get_dof_map().n_dofs());
  assert (global_dof_number < current_local_nonlinear_solution->size());

  return (*current_local_nonlinear_solution)(global_dof_number);
}
<commit_msg>Make sure print_solutions is initialized to a sane default<commit_after>#include "diff_system.h"
#include "dof_map.h"
#include "numeric_vector.h"
#include "time_solver.h"

DifferentiableSystem::DifferentiableSystem
                      (EquationSystems& es,
                       const std::string& name,
                       const unsigned int number) :
  Parent      (es, name, number),
  compute_internal_sides(false),
  postprocess_sides(false),
  time_solver (NULL),
  time(0.),
  deltat(1.),
  print_solution_norms(false),
  print_solutions(false),
  print_residual_norms(false),
  print_residuals(false),
  print_jacobian_norms(false),
  print_jacobians(false),
  current_local_nonlinear_solution(NumericVector<Number>::build())
{
  untested();
}

DifferentiableSystem::~DifferentiableSystem ()
{
}

void DifferentiableSystem::reinit ()
{
  Parent::reinit();

  // Resize the serial nonlinear solution for the current mesh
  current_local_nonlinear_solution->init (this->n_dofs());

  time_solver->reinit();
}

void DifferentiableSystem::init_data ()
{
  // First, allocate a vector for the iterate in our quasi_Newton
  // solver

  // FIXME - there really ought to be a way to just use the System
  // solution vector if the solver doesn't need an extra vector!

  // We don't want to project more solutions than we have to
//  this->add_vector("_nonlinear_solution", false);
  this->add_vector("_nonlinear_solution");
//  this->project_solution_on_reinit() = false;

  // Next, give us flags for every variable that might be time
  // evolving
  _time_evolving.resize(this->n_vars(), false);

  // Do any initialization our solvers need
  assert (time_solver.get() != NULL);
  time_solver->init();

  // Next initialize ImplicitSystem data
  Parent::init_data();

  // Finally initialize solution/residual/jacobian data structures
  unsigned int n_vars = this->n_vars();

  dof_indices_var.resize(n_vars);

  elem_subsolutions.clear();
  elem_subsolutions.reserve(n_vars);
  elem_subresiduals.clear();
  elem_subresiduals.reserve(n_vars);
  elem_subjacobians.clear();
  elem_subjacobians.resize(n_vars);
  for (unsigned int i=0; i != n_vars; ++i)
    {
      elem_subsolutions.push_back(new DenseSubVector<Number>(elem_solution));
      elem_subresiduals.push_back(new DenseSubVector<Number>(elem_residual));
      elem_subjacobians[i].clear();
      elem_subjacobians[i].reserve(n_vars);

      for (unsigned int j=0; j != n_vars; ++j)
        {
          elem_subjacobians[i].push_back
            (new DenseSubMatrix<Number>(elem_jacobian));
        }
    }

  // Resize the serial nonlinear solution for the current mesh
  current_local_nonlinear_solution->init (this->n_dofs());
}

void DifferentiableSystem::assemble ()
{
  this->assembly(true, true);
}

void DifferentiableSystem::solve ()
{
  time_solver->solve();
}

Number DifferentiableSystem::current_nonlinear_solution (const unsigned int global_dof_number) const
{
  // Check the sizes
  assert (global_dof_number < this->get_dof_map().n_dofs());
  assert (global_dof_number < current_local_nonlinear_solution->size());

  return (*current_local_nonlinear_solution)(global_dof_number);
}
<|endoftext|>


<commit_before>// Source : https://oj.leetcode.com/problems/3sum/
// Author : Hao Chen
// Date   : 2014-07-22

/**********************************************************************************
*
* Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0?
* Find all unique triplets in the array which gives the sum of zero.
*
* Note:
*
* Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
* The solution set must not contain duplicate triplets.
*
*     For example, given array S = {-1 0 1 2 -1 -4},
*
*     A solution set is:
*     (-1, 0, 1)
*     (-1, -1, 2)
*
*
**********************************************************************************/

#include <stdio.h>
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;

/*
 *   Simlar like "Two Number" problem, we can have the simlar solution.
 *
 *   Suppose the input array is S[0..n-1], 3SUM can be solved in O(n^2) time on average by
 *   inserting each number S[i] into a hash table, and then for each index i and j,
 *   checking whether the hash table contains the integer - (s[i]+s[j])
 *
 *   Alternatively, the algorithm below first sorts the input array and then tests all
 *   possible pairs in a careful order that avoids the need to binary search for the pairs
 *   in the sorted list, achieving worst-case O(n^n)
 *
 *   Solution:  Quadratic algorithm
 *   http://en.wikipedia.org/wiki/3SUM
 *
 */
vector<vector<int> > threeSum(vector<int> &num) {

    vector< vector<int> > result;

    //sort the array, this is the key
    sort(num.begin(), num.end());

    int n = num.size();

    for (int i=0; i<n-2; i++) {
        //skip the duplication
        if (i>0 && num[i-1]==num[i]) continue;
        int a = num[i];
        int low = i+1;
        int high = n-1;
        while ( low < high ) {
            int b = num[low];
            int c = num[high];
            if (a+b+c == 0) {
                //got the soultion
                vector<int> v;
                v.push_back(a);
                v.push_back(b);
                v.push_back(c);
                result.push_back(v);
                // Continue search for all triplet combinations summing to zero.
                //skip the duplication
                while(low<n-1 && num[low]==num[low+1]) low++;
                while(high>0 && num[high]==num[high-1]) high--;
                low++;
                high--;
            } else if (a+b+c > 0) {
                //skip the duplication
                while(high>0 && num[high]==num[high-1]) high--;
                high--;
            } else{
                //skip the duplication
                while(low<n && num[low]==num[low+1]) low++;
                low++;
            }
        }
    }
    return result;
}

//using combination method could meet <<Time Limit Exceeded>> error
vector<vector<int> > combination(vector<int> &v, int k);
bool isSumZero(vector<int>& v);
int sum(vector<int>& v);

vector<vector<int> > threeSum2(vector<int> &num) {
    vector< vector<int> > result;
    vector< vector<int> > r = combination(num, 3);
    for (int i=0; i<r.size(); i++){
        if (isSumZero(r[i])){
            result.push_back(r[i]);
        }
    }
    return result;
}

bool isSumZero(vector<int>& v){
    return sum(v)==0;
}

int sum(vector<int>& v){
    int s=0;
    for(int i=0; i<v.size(); i++){
        s += v[i];
    }
    return s;
}

vector<vector<int> > combination(vector<int> &v, int k) {

    vector<vector<int> > result;
    vector<int> d;
    int n = v.size();
    for (int i=0; i<n; i++){
        d.push_back( (i<k) ? 1 : 0 );
    }

    //1) from the left, find the [1,0] pattern, change it to [0,1]
    //2) move all of the 1 before the pattern to the most left side
    //3) check all of 1 move to the right
    while(1){
        vector<int> tmp;
        for(int x=0; x<n; x++){
            if (d[x]) tmp.push_back(v[x]);
        }
        sort(tmp.begin(), tmp.end());
        result.push_back(tmp);
        //step 1), find [1,0] pattern
        int i;
        bool found = false;
        int ones =0;
        for(i=0; i<n-1; i++){

            if (d[i]==1 && d[i+1]==0){
                d[i]=0; d[i+1]=1;
                found = true;
                //step 2) move all of right 1 to the most left side
                for (int j=0; j<i; j++){
                    d[j]=( ones > 0 ) ? 1 : 0;
                    ones--;
                }
                break;
            }
            if (d[i]==1) ones++;
        }
        if (!found){
            break;
        }

    }
    return result;
}

void printMatrix(vector<vector<int> > &matrix)
{
    for(int i=0; i<matrix.size(); i++){
        printf("{");
        for(int j=0; j< matrix[i].size(); j++) {
            printf("%3d ", matrix[i][j]) ;
        }
        printf("}\n");
    }
    cout << endl;
}

int main()
{
    //int a[] = {-1, 0, 1, 2, -1, 1, -4};
    int a[] = {-1, 1, 1, 1, -1, -1, 0,0,0};
    vector<int> n(a, a+sizeof(a)/sizeof(int));
    vector< vector<int> > result = threeSum(n);
    printMatrix(result);
    return 0;
}
<commit_msg>array index out of bounds, fix to low<n-1<commit_after>// Source : https://oj.leetcode.com/problems/3sum/
// Author : Hao Chen
// Date   : 2014-07-22

/**********************************************************************************
*
* Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0?
* Find all unique triplets in the array which gives the sum of zero.
*
* Note:
*
* Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
* The solution set must not contain duplicate triplets.
*
*     For example, given array S = {-1 0 1 2 -1 -4},
*
*     A solution set is:
*     (-1, 0, 1)
*     (-1, -1, 2)
*
*
**********************************************************************************/

#include <stdio.h>
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;

/*
 *   Simlar like "Two Number" problem, we can have the simlar solution.
 *
 *   Suppose the input array is S[0..n-1], 3SUM can be solved in O(n^2) time on average by
 *   inserting each number S[i] into a hash table, and then for each index i and j,
 *   checking whether the hash table contains the integer - (s[i]+s[j])
 *
 *   Alternatively, the algorithm below first sorts the input array and then tests all
 *   possible pairs in a careful order that avoids the need to binary search for the pairs
 *   in the sorted list, achieving worst-case O(n^n)
 *
 *   Solution:  Quadratic algorithm
 *   http://en.wikipedia.org/wiki/3SUM
 *
 */
vector<vector<int> > threeSum(vector<int> &num) {

    vector< vector<int> > result;

    //sort the array, this is the key
    sort(num.begin(), num.end());

    int n = num.size();

    for (int i=0; i<n-2; i++) {
        //skip the duplication
        if (i>0 && num[i-1]==num[i]) continue;
        int a = num[i];
        int low = i+1;
        int high = n-1;
        while ( low < high ) {
            int b = num[low];
            int c = num[high];
            if (a+b+c == 0) {
                //got the soultion
                vector<int> v;
                v.push_back(a);
                v.push_back(b);
                v.push_back(c);
                result.push_back(v);
                // Continue search for all triplet combinations summing to zero.
                //skip the duplication
                while(low<n-1 && num[low]==num[low+1]) low++;
                while(high>0 && num[high]==num[high-1]) high--;
                low++;
                high--;
            } else if (a+b+c > 0) {
                //skip the duplication
                while(high>0 && num[high]==num[high-1]) high--;
                high--;
            } else{
                //skip the duplication
                while(low<n-1 && num[low]==num[low+1]) low++;
                low++;
            }
        }
    }
    return result;
}

//using combination method could meet <<Time Limit Exceeded>> error
vector<vector<int> > combination(vector<int> &v, int k);
bool isSumZero(vector<int>& v);
int sum(vector<int>& v);

vector<vector<int> > threeSum2(vector<int> &num) {
    vector< vector<int> > result;
    vector< vector<int> > r = combination(num, 3);
    for (int i=0; i<r.size(); i++){
        if (isSumZero(r[i])){
            result.push_back(r[i]);
        }
    }
    return result;
}

bool isSumZero(vector<int>& v){
    return sum(v)==0;
}

int sum(vector<int>& v){
    int s=0;
    for(int i=0; i<v.size(); i++){
        s += v[i];
    }
    return s;
}

vector<vector<int> > combination(vector<int> &v, int k) {

    vector<vector<int> > result;
    vector<int> d;
    int n = v.size();
    for (int i=0; i<n; i++){
        d.push_back( (i<k) ? 1 : 0 );
    }

    //1) from the left, find the [1,0] pattern, change it to [0,1]
    //2) move all of the 1 before the pattern to the most left side
    //3) check all of 1 move to the right
    while(1){
        vector<int> tmp;
        for(int x=0; x<n; x++){
            if (d[x]) tmp.push_back(v[x]);
        }
        sort(tmp.begin(), tmp.end());
        result.push_back(tmp);
        //step 1), find [1,0] pattern
        int i;
        bool found = false;
        int ones =0;
        for(i=0; i<n-1; i++){

            if (d[i]==1 && d[i+1]==0){
                d[i]=0; d[i+1]=1;
                found = true;
                //step 2) move all of right 1 to the most left side
                for (int j=0; j<i; j++){
                    d[j]=( ones > 0 ) ? 1 : 0;
                    ones--;
                }
                break;
            }
            if (d[i]==1) ones++;
        }
        if (!found){
            break;
        }

    }
    return result;
}

void printMatrix(vector<vector<int> > &matrix)
{
    for(int i=0; i<matrix.size(); i++){
        printf("{");
        for(int j=0; j< matrix[i].size(); j++) {
            printf("%3d ", matrix[i][j]) ;
        }
        printf("}\n");
    }
    cout << endl;
}

int main()
{
    //int a[] = {-1, 0, 1, 2, -1, 1, -4};
    int a[] = {-1, 1, 1, 1, -1, -1, 0,0,0};
    vector<int> n(a, a+sizeof(a)/sizeof(int));
    vector< vector<int> > result = threeSum(n);
    printMatrix(result);
    return 0;
}
<|endoftext|>


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

#include "src/main/cpp/startup_options.h"
#include "googletest/include/gtest/gtest.h"

namespace blaze {

void ExpectIsNullaryOption(const StartupOptions* options,
                           const std::string& flag_name) {
  EXPECT_TRUE(options->IsNullary("--" + flag_name));
  EXPECT_TRUE(options->IsNullary("--no" + flag_name));

  EXPECT_FALSE(options->IsNullary("--" + flag_name + "__invalid"));

  EXPECT_DEATH(options->IsNullary("--" + flag_name + "=foo"),
               ("In argument '--" + flag_name + "=foo': option '--" +
                flag_name + "' does not take a value")
                   .c_str());

  EXPECT_DEATH(options->IsNullary("--no" + flag_name + "=foo"),
               ("In argument '--no" + flag_name + "=foo': option '--no" +
                flag_name + "' does not take a value")
                   .c_str());

  EXPECT_FALSE(options->IsUnary("--" + flag_name));
  EXPECT_FALSE(options->IsUnary("--no" + flag_name));
}

void ExpectIsUnaryOption(const StartupOptions* options,
                         const std::string& flag_name) {
  EXPECT_TRUE(options->IsUnary("--" + flag_name));
  EXPECT_TRUE(options->IsUnary("--" + flag_name + "="));
  EXPECT_TRUE(options->IsUnary("--" + flag_name + "=foo"));

  EXPECT_FALSE(options->IsUnary("--" + flag_name + "__invalid"));
  EXPECT_FALSE(options->IsNullary("--" + flag_name));
  EXPECT_FALSE(options->IsNullary("--no" + flag_name));
}

void ParseStartupOptionsAndExpectWarning(
    StartupOptions* startup_options,
    const std::vector<std::string>& options_to_parse,
    const std::string& expected_warning) {
  std::vector<RcStartupFlag> flags;
  for (std::string option : options_to_parse) {
    flags.push_back(RcStartupFlag("", option));
  }

  std::string error;
  EXPECT_EQ(blaze_exit_code::SUCCESS,
            startup_options->ProcessArgs(flags, &error));
  ASSERT_EQ("", error);

  testing::internal::CaptureStderr();
  startup_options->MaybeLogStartupOptionWarnings();
  const std::string& output = testing::internal::GetCapturedStderr();

  EXPECT_EQ(expected_warning, output);
}

}  // namespace blaze
<commit_msg>Automatic ClangTidyPerformance code cleanup.<commit_after>// Copyright 2018 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/test/cpp/test_util.h"

#include "src/main/cpp/startup_options.h"
#include "googletest/include/gtest/gtest.h"

namespace blaze {

void ExpectIsNullaryOption(const StartupOptions* options,
                           const std::string& flag_name) {
  EXPECT_TRUE(options->IsNullary("--" + flag_name));
  EXPECT_TRUE(options->IsNullary("--no" + flag_name));

  EXPECT_FALSE(options->IsNullary("--" + flag_name + "__invalid"));

  EXPECT_DEATH(options->IsNullary("--" + flag_name + "=foo"),
               ("In argument '--" + flag_name + "=foo': option '--" +
                flag_name + "' does not take a value")
                   .c_str());

  EXPECT_DEATH(options->IsNullary("--no" + flag_name + "=foo"),
               ("In argument '--no" + flag_name + "=foo': option '--no" +
                flag_name + "' does not take a value")
                   .c_str());

  EXPECT_FALSE(options->IsUnary("--" + flag_name));
  EXPECT_FALSE(options->IsUnary("--no" + flag_name));
}

void ExpectIsUnaryOption(const StartupOptions* options,
                         const std::string& flag_name) {
  EXPECT_TRUE(options->IsUnary("--" + flag_name));
  EXPECT_TRUE(options->IsUnary("--" + flag_name + "="));
  EXPECT_TRUE(options->IsUnary("--" + flag_name + "=foo"));

  EXPECT_FALSE(options->IsUnary("--" + flag_name + "__invalid"));
  EXPECT_FALSE(options->IsNullary("--" + flag_name));
  EXPECT_FALSE(options->IsNullary("--no" + flag_name));
}

void ParseStartupOptionsAndExpectWarning(
    StartupOptions* startup_options,
    const std::vector<std::string>& options_to_parse,
    const std::string& expected_warning) {
  std::vector<RcStartupFlag> flags;
  flags.reserve(options_to_parse.size());
  for (const std::string& option : options_to_parse) {
    flags.push_back(RcStartupFlag("", option));
  }

  std::string error;
  EXPECT_EQ(blaze_exit_code::SUCCESS,
            startup_options->ProcessArgs(flags, &error));
  ASSERT_EQ("", error);

  testing::internal::CaptureStderr();
  startup_options->MaybeLogStartupOptionWarnings();
  const std::string& output = testing::internal::GetCapturedStderr();

  EXPECT_EQ(expected_warning, output);
}

}  // namespace blaze
<|endoftext|>


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

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE method

#include <boost/test/unit_test.hpp>

#include "json/cJSON.h"
#include "peer.h"
#include "router.h"
#include "state.h"
#include "table.h"

static const char *method_no_args_path = "/method_no_args/";

static const int INVALID_PARAMS_ERROR = -32602;

extern "C" {
	int send_message(struct peer *p, const char *rendered, size_t len)
	{
		(void)p;
		(void)rendered;
		(void)len;
		return 0;
	}

	int add_io(struct peer *p)
	{
		(void)p;
		return 0;
	}

	void remove_io(const struct peer *p)
	{
		(void)p;
		return;
	}
}

struct F {
	F()
	{
		state_hashtable_create();
		owner_peer = alloc_peer(-1);
		call_peer = alloc_peer(-1);
	}
	~F()
	{
		free_peer(call_peer);
		free_peer(owner_peer);
		state_hashtable_delete();
	}

	struct peer *owner_peer;
	struct peer *call_peer;
};

static cJSON *create_call_json_rpc(const char *path_string)
{
	cJSON *root = cJSON_CreateObject();
	BOOST_REQUIRE(root != NULL);
	cJSON_AddStringToObject(root, "method", "call");
	cJSON_AddStringToObject(root, "id", "id_1");
	cJSON *params = cJSON_CreateObject();
	BOOST_REQUIRE(params != NULL);
	cJSON_AddItemToObject(root, "params", params);
	cJSON_AddStringToObject(params, "path", path_string);

	return root;
}

static cJSON *create_call_json_rpc_wrong_id_type(const char *path_string)
{
	cJSON *root = cJSON_CreateObject();
	BOOST_REQUIRE(root != NULL);
	cJSON_AddStringToObject(root, "method", "call");
	cJSON_AddTrueToObject(root, "id");
	cJSON *params = cJSON_CreateObject();
	BOOST_REQUIRE(params != NULL);
	cJSON_AddItemToObject(root, "params", params);
	cJSON_AddStringToObject(params, "path", path_string);

	return root;
}

static void check_invalid_params(const cJSON *error)
{
	cJSON *code = cJSON_GetObjectItem(error, "code");
	if (code != NULL) {
		BOOST_CHECK(code->type == cJSON_Number);
		BOOST_CHECK(code->valueint == INVALID_PARAMS_ERROR);
	} else {
		BOOST_FAIL("No code object!");
	}

	cJSON *message = cJSON_GetObjectItem(error, "message");
	if (message != NULL) {
		BOOST_CHECK(message->type == cJSON_String);
		BOOST_CHECK(strcmp(message->valuestring, "Invalid params") == 0);
	} else {
		BOOST_FAIL("No message object!");
	}
}

BOOST_FIXTURE_TEST_CASE(delete_nonexisting_state, F)
{
	const char path[] = "/foo/bar/";
	int ret = remove_state_or_method_from_peer(owner_peer, path);
	BOOST_CHECK(ret == -1);
}

BOOST_FIXTURE_TEST_CASE(call_wrong_path, F)
{

	cJSON *error = add_state_or_method_to_peer(owner_peer, "/foo/bar", NULL);
	BOOST_CHECK(error == NULL);

	cJSON *call_json_rpc = create_call_json_rpc(method_no_args_path);
	error = set_or_call(owner_peer, "/bar/foo", NULL, call_json_rpc, METHOD);
	cJSON_Delete(call_json_rpc);

	if (error != NULL) {
		check_invalid_params(error);
		cJSON_Delete(error);
	} else {
		BOOST_FAIL("expected to get an error!");
	}
}

BOOST_FIXTURE_TEST_CASE(add_method_twice, F)
{
	const char path[] = "/foo/bar";

	cJSON *error = add_state_or_method_to_peer(owner_peer, path, NULL);
	BOOST_CHECK(error == NULL);

	error = add_state_or_method_to_peer(owner_peer, path, NULL);
	BOOST_REQUIRE(error != NULL);
	check_invalid_params(error);
	cJSON_Delete(error);
}

BOOST_FIXTURE_TEST_CASE(add_method_existing_state, F)
{
	const char path[] = "/foo/bar";
	int state_value = 12345;

	cJSON *value = cJSON_CreateNumber(state_value);
	cJSON *error = add_state_or_method_to_peer(owner_peer, path, value);
	BOOST_CHECK(error == NULL);
	cJSON_Delete(value);

	error = add_state_or_method_to_peer(owner_peer, path, NULL);
	BOOST_REQUIRE(error != NULL);
	check_invalid_params(error);
	cJSON_Delete(error);
}

BOOST_FIXTURE_TEST_CASE(call_on_state, F)
{
	const char path[] = "/foo/bar";
	int state_value = 12345;

	cJSON *value = cJSON_CreateNumber(state_value);
	cJSON *error = add_state_or_method_to_peer(owner_peer, path, value);
	BOOST_CHECK(error == NULL);
	cJSON_Delete(value);

	cJSON *call_json_rpc = create_call_json_rpc(method_no_args_path);
	error = set_or_call(call_peer, path, NULL, call_json_rpc, METHOD);
	cJSON_Delete(call_json_rpc);

	if (error != NULL) {
		check_invalid_params(error);
		cJSON_Delete(error);
	} else {
		BOOST_FAIL("expected to get an error!");
	}
}

BOOST_FIXTURE_TEST_CASE(double_free_method, F)
{
	const char path[] = "/foo/bar";
	cJSON *error = add_state_or_method_to_peer(owner_peer, path, NULL);
	BOOST_CHECK(error == NULL);

	int ret = remove_state_or_method_from_peer(owner_peer, path);
	BOOST_CHECK(ret == 0);

	ret = remove_state_or_method_from_peer(owner_peer, path);
	BOOST_CHECK(ret == -1);
}

BOOST_FIXTURE_TEST_CASE(call_not_by_owner, F)
{
	cJSON *error = add_state_or_method_to_peer(owner_peer, method_no_args_path, NULL);
	BOOST_CHECK(error == NULL);

	cJSON *call_json_rpc = create_call_json_rpc(method_no_args_path);
	error = set_or_call(owner_peer, method_no_args_path, NULL, call_json_rpc, METHOD);
	cJSON_Delete(call_json_rpc);
	if (error != NULL) {
		check_invalid_params(error);
		cJSON_Delete(error);
	} else {
		BOOST_FAIL("expected to get an error!");
	}
}

BOOST_FIXTURE_TEST_CASE(set_wrong_id_type, F)
{
	cJSON *error = add_state_or_method_to_peer(owner_peer, method_no_args_path, NULL);
	BOOST_CHECK(error == NULL);

	cJSON *call_json_rpc = create_call_json_rpc_wrong_id_type(method_no_args_path);
	error = set_or_call(call_peer, method_no_args_path, NULL, call_json_rpc, METHOD);
	cJSON_Delete(call_json_rpc);

	if ((error != NULL) && (error != (cJSON *)ROUTED_MESSAGE)) {
		check_invalid_params(error);
		cJSON_Delete(error);
	} else  {
		BOOST_FAIL("expected to get an error!");
	}
}
<commit_msg>Add test for correct method call.<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) <2015> <Stephan Gatzka>
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE method

#include <boost/test/unit_test.hpp>

#include "json/cJSON.h"
#include "peer.h"
#include "router.h"
#include "state.h"
#include "table.h"

static const char *method_no_args_path = "/method_no_args/";

static const int INVALID_PARAMS_ERROR = -32602;

extern "C" {
	int send_message(struct peer *p, const char *rendered, size_t len)
	{
		(void)p;
		(void)rendered;
		(void)len;
		return 0;
	}

	int add_io(struct peer *p)
	{
		(void)p;
		return 0;
	}

	void remove_io(const struct peer *p)
	{
		(void)p;
		return;
	}
}

struct F {
	F()
	{
		state_hashtable_create();
		owner_peer = alloc_peer(-1);
		call_peer = alloc_peer(-1);
	}
	~F()
	{
		free_peer(call_peer);
		free_peer(owner_peer);
		state_hashtable_delete();
	}

	struct peer *owner_peer;
	struct peer *call_peer;
};

static cJSON *create_call_json_rpc(const char *path_string)
{
	cJSON *root = cJSON_CreateObject();
	BOOST_REQUIRE(root != NULL);
	cJSON_AddStringToObject(root, "method", "call");
	cJSON_AddStringToObject(root, "id", "id_1");
	cJSON *params = cJSON_CreateObject();
	BOOST_REQUIRE(params != NULL);
	cJSON_AddItemToObject(root, "params", params);
	cJSON_AddStringToObject(params, "path", path_string);

	return root;
}

static cJSON *create_call_json_rpc_wrong_id_type(const char *path_string)
{
	cJSON *root = cJSON_CreateObject();
	BOOST_REQUIRE(root != NULL);
	cJSON_AddStringToObject(root, "method", "call");
	cJSON_AddTrueToObject(root, "id");
	cJSON *params = cJSON_CreateObject();
	BOOST_REQUIRE(params != NULL);
	cJSON_AddItemToObject(root, "params", params);
	cJSON_AddStringToObject(params, "path", path_string);

	return root;
}

static void check_invalid_params(const cJSON *error)
{
	cJSON *code = cJSON_GetObjectItem(error, "code");
	if (code != NULL) {
		BOOST_CHECK(code->type == cJSON_Number);
		BOOST_CHECK(code->valueint == INVALID_PARAMS_ERROR);
	} else {
		BOOST_FAIL("No code object!");
	}

	cJSON *message = cJSON_GetObjectItem(error, "message");
	if (message != NULL) {
		BOOST_CHECK(message->type == cJSON_String);
		BOOST_CHECK(strcmp(message->valuestring, "Invalid params") == 0);
	} else {
		BOOST_FAIL("No message object!");
	}
}

BOOST_FIXTURE_TEST_CASE(delete_nonexisting_state, F)
{
	const char path[] = "/foo/bar/";
	int ret = remove_state_or_method_from_peer(owner_peer, path);
	BOOST_CHECK(ret == -1);
}

BOOST_FIXTURE_TEST_CASE(call_wrong_path, F)
{

	cJSON *error = add_state_or_method_to_peer(owner_peer, "/foo/bar", NULL);
	BOOST_CHECK(error == NULL);

	cJSON *call_json_rpc = create_call_json_rpc(method_no_args_path);
	error = set_or_call(owner_peer, "/bar/foo", NULL, call_json_rpc, METHOD);
	cJSON_Delete(call_json_rpc);

	if (error != NULL) {
		check_invalid_params(error);
		cJSON_Delete(error);
	} else {
		BOOST_FAIL("expected to get an error!");
	}
}

BOOST_FIXTURE_TEST_CASE(add_method_twice, F)
{
	const char path[] = "/foo/bar";

	cJSON *error = add_state_or_method_to_peer(owner_peer, path, NULL);
	BOOST_CHECK(error == NULL);

	error = add_state_or_method_to_peer(owner_peer, path, NULL);
	BOOST_REQUIRE(error != NULL);
	check_invalid_params(error);
	cJSON_Delete(error);
}

BOOST_FIXTURE_TEST_CASE(add_method_existing_state, F)
{
	const char path[] = "/foo/bar";
	int state_value = 12345;

	cJSON *value = cJSON_CreateNumber(state_value);
	cJSON *error = add_state_or_method_to_peer(owner_peer, path, value);
	BOOST_CHECK(error == NULL);
	cJSON_Delete(value);

	error = add_state_or_method_to_peer(owner_peer, path, NULL);
	BOOST_REQUIRE(error != NULL);
	check_invalid_params(error);
	cJSON_Delete(error);
}

BOOST_FIXTURE_TEST_CASE(call_on_state, F)
{
	const char path[] = "/foo/bar";
	int state_value = 12345;

	cJSON *value = cJSON_CreateNumber(state_value);
	cJSON *error = add_state_or_method_to_peer(owner_peer, path, value);
	BOOST_CHECK(error == NULL);
	cJSON_Delete(value);

	cJSON *call_json_rpc = create_call_json_rpc(method_no_args_path);
	error = set_or_call(call_peer, path, NULL, call_json_rpc, METHOD);
	cJSON_Delete(call_json_rpc);

	if (error != NULL) {
		check_invalid_params(error);
		cJSON_Delete(error);
	} else {
		BOOST_FAIL("expected to get an error!");
	}
}

BOOST_FIXTURE_TEST_CASE(double_free_method, F)
{
	const char path[] = "/foo/bar";
	cJSON *error = add_state_or_method_to_peer(owner_peer, path, NULL);
	BOOST_CHECK(error == NULL);

	int ret = remove_state_or_method_from_peer(owner_peer, path);
	BOOST_CHECK(ret == 0);

	ret = remove_state_or_method_from_peer(owner_peer, path);
	BOOST_CHECK(ret == -1);
}

BOOST_FIXTURE_TEST_CASE(call_not_by_owner, F)
{
	cJSON *error = add_state_or_method_to_peer(owner_peer, method_no_args_path, NULL);
	BOOST_CHECK(error == NULL);

	cJSON *call_json_rpc = create_call_json_rpc(method_no_args_path);
	error = set_or_call(owner_peer, method_no_args_path, NULL, call_json_rpc, METHOD);
	cJSON_Delete(call_json_rpc);
	if (error != NULL) {
		check_invalid_params(error);
		cJSON_Delete(error);
	} else {
		BOOST_FAIL("expected to get an error!");
	}
}

BOOST_FIXTURE_TEST_CASE(correct_call, F)
{
	cJSON *error = add_state_or_method_to_peer(owner_peer, method_no_args_path, NULL);
	BOOST_CHECK(error == NULL);

	cJSON *call_json_rpc = create_call_json_rpc(method_no_args_path);
	error = set_or_call(call_peer, method_no_args_path, NULL, call_json_rpc, METHOD);
	cJSON_Delete(call_json_rpc);
	BOOST_CHECK(error == (cJSON *)ROUTED_MESSAGE);
}

BOOST_FIXTURE_TEST_CASE(set_wrong_id_type, F)
{
	cJSON *error = add_state_or_method_to_peer(owner_peer, method_no_args_path, NULL);
	BOOST_CHECK(error == NULL);

	cJSON *call_json_rpc = create_call_json_rpc_wrong_id_type(method_no_args_path);
	error = set_or_call(call_peer, method_no_args_path, NULL, call_json_rpc, METHOD);
	cJSON_Delete(call_json_rpc);

	if ((error != NULL) && (error != (cJSON *)ROUTED_MESSAGE)) {
		check_invalid_params(error);
		cJSON_Delete(error);
	} else  {
		BOOST_FAIL("expected to get an error!");
	}
}
<|endoftext|>


<commit_before>/*ckwg +5
 * Copyright 2012-2013 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include "helpers/pipeline_builder.h"
#include "helpers/tool_main.h"
#include "helpers/tool_usage.h"

#include <vistk/pipeline_util/pipe_declaration_types.h>

#include <vistk/pipeline/config.h>
#include <vistk/pipeline/modules.h>
#include <vistk/pipeline/pipeline.h>
#include <vistk/pipeline/pipeline_exception.h>
#include <vistk/pipeline/process.h>
#include <vistk/pipeline/process_cluster.h>
#include <vistk/pipeline/types.h>

#include <vistk/utilities/path.h>

#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/foreach.hpp>
#include <boost/variant.hpp>

#include <iostream>
#include <set>
#include <stdexcept>
#include <string>

#include <cstdlib>

class config_printer
  : public boost::static_visitor<>
{
  public:
    config_printer(std::ostream& ostr, vistk::pipeline_t const& pipe, vistk::config_t const& conf);
    ~config_printer();

    void operator () (vistk::config_pipe_block const& config_block);
    void operator () (vistk::process_pipe_block const& process_block);
    void operator () (vistk::connect_pipe_block const& connect_block) const;

    void output_process_defaults();
  private:
    void print_config_value(vistk::config_value_t const& config_value) const;
    void output_process_by_name(vistk::process::name_t const& name, bool fatal_if_no_process);
    void output_process_block(vistk::process_t const& name, std::string const& kind);
    void output_process(vistk::process_t const& proc);

    typedef std::set<vistk::process::name_t> process_set_t;

    std::ostream& m_ostr;
    vistk::pipeline_t const m_pipe;
    vistk::config_t const m_config;
    process_set_t m_visited;
};

int
tool_main(int argc, char* argv[])
{
  vistk::load_known_modules();

  boost::program_options::options_description desc;
  desc
    .add(tool_common_options())
    .add(pipeline_common_options())
    .add(pipeline_input_options())
    .add(pipeline_output_options());

  boost::program_options::variables_map const vm = tool_parse(argc, argv, desc);

  pipeline_builder const builder(vm, desc);

  vistk::pipeline_t const pipe = builder.pipeline();
  vistk::config_t const config = builder.config();
  vistk::pipe_blocks const blocks = builder.blocks();

  if (!pipe)
  {
    std::cerr << "Error: Unable to bake pipeline" << std::endl;

    return EXIT_FAILURE;
  }

  std::ostream* postr;
  boost::filesystem::ofstream fout;

  vistk::path_t const opath = vm["output"].as<vistk::path_t>();

  if (opath == vistk::path_t("-"))
  {
    postr = &std::cout;
  }
  else
  {
    fout.open(opath);

    if (fout.bad())
    {
      std::cerr << "Error: Unable to open output file" << std::endl;

      return EXIT_FAILURE;
    }

    postr = &fout;
  }

  std::ostream& ostr = *postr;

  config_printer printer(ostr, pipe, config);

  std::for_each(blocks.begin(), blocks.end(), boost::apply_visitor(printer));

  printer.output_process_defaults();

  return EXIT_SUCCESS;
}

config_printer
::config_printer(std::ostream& ostr, vistk::pipeline_t const& pipe, vistk::config_t const& conf)
  : m_ostr(ostr)
  , m_pipe(pipe)
  , m_config(conf)
{
}

config_printer
::~config_printer()
{
}

class key_printer
{
  public:
    key_printer(std::ostream& ostr);
    ~key_printer();

    void operator () (vistk::config_value_t const& config_value) const;
  private:
    std::ostream& m_ostr;
};

void
config_printer
::operator () (vistk::config_pipe_block const& config_block)
{
  vistk::config::keys_t const& keys = config_block.key;
  vistk::config_values_t const& values = config_block.values;

  vistk::config::key_t const key_path = boost::join(keys, vistk::config::block_sep);

  m_ostr << "config " << key_path << std::endl;

  key_printer const printer(m_ostr);

  std::for_each(values.begin(), values.end(), printer);

  output_process_by_name(key_path, false);
}

void
config_printer
::operator () (vistk::process_pipe_block const& process_block)
{
  vistk::process::name_t const& name = process_block.name;
  vistk::process::type_t const& type = process_block.type;
  vistk::config_values_t const& values = process_block.config_values;

  m_ostr << "process " << name << std::endl;
  m_ostr << "  :: " << type << std::endl;

  key_printer const printer(m_ostr);

  std::for_each(values.begin(), values.end(), printer);

  output_process_by_name(name, true);
}

void
config_printer
::operator () (vistk::connect_pipe_block const& connect_block) const
{
  vistk::process::port_addr_t const& upstream_addr = connect_block.from;
  vistk::process::port_addr_t const& downstream_addr = connect_block.to;

  vistk::process::name_t const& upstream_name = upstream_addr.first;
  vistk::process::port_t const& upstream_port = upstream_addr.second;
  vistk::process::name_t const& downstream_name = downstream_addr.first;
  vistk::process::port_t const& downstream_port = downstream_addr.second;

  m_ostr << "connect from " << upstream_name << "." << upstream_port << std::endl;
  m_ostr << "        to   " << downstream_name << "." << downstream_port << std::endl;

  m_ostr << std::endl;
}

void
config_printer
::output_process_defaults()
{
  vistk::process::names_t const cluster_names = m_pipe->cluster_names();

  BOOST_FOREACH (vistk::process::name_t const& name, cluster_names)
  {
    if (m_visited.count(name))
    {
      continue;
    }

    vistk::process_cluster_t const cluster = m_pipe->cluster_by_name(name);
    vistk::process_t const proc = boost::static_pointer_cast<vistk::process>(cluster);

    static std::string const kind = "cluster";

    output_process_block(proc, kind);
  }

  vistk::process::names_t const process_names = m_pipe->process_names();

  BOOST_FOREACH (vistk::process::name_t const& name, process_names)
  {
    if (m_visited.count(name))
    {
      continue;
    }

    vistk::process_t const proc = m_pipe->process_by_name(name);

    static std::string const kind = "process";

    output_process_block(proc, kind);
  }
}

void
config_printer
::output_process_by_name(vistk::process::name_t const& name, bool fatal_if_no_process)
{
  vistk::process_t proc;

  if (!m_visited.count(name))
  {
    try
    {
      proc = m_pipe->process_by_name(name);
    }
    catch (vistk::no_such_process_exception const& /*e*/)
    {
      try
      {
        vistk::process_cluster_t const cluster = m_pipe->cluster_by_name(name);

        proc = boost::static_pointer_cast<vistk::process>(cluster);
      }
      catch (vistk::no_such_process_exception const& /*e*/)
      {
        if (fatal_if_no_process)
        {
          std::string const reason = "A process block did not result in a process being "
                                     "added to the pipeline: " + name;

          throw std::logic_error(reason);
        }
      }
    }
  }

  if (proc)
  {
    output_process(proc);
  }
  else
  {
    m_ostr << std::endl;
  }
}

void
config_printer
::output_process_block(vistk::process_t const& proc, std::string const& kind)
{
  vistk::process::name_t const name = proc->name();
  vistk::process::type_t const type = proc->type();

  m_ostr << "# Defaults for \'" << name << "\' " << kind << ":" << std::endl;
  m_ostr << "config " << name << std::endl;
  m_ostr << "#  :: " << type << std::endl;

  output_process(proc);
}

void
config_printer
::output_process(vistk::process_t const& proc)
{
  vistk::process::name_t const name = proc->name();
  vistk::config::keys_t const keys = proc->available_config();

  BOOST_FOREACH (vistk::config::key_t const& key, keys)
  {
    if (boost::starts_with(key, "_"))
    {
      continue;
    }

    m_ostr << std::endl;

    vistk::process::conf_info_t const& info = proc->config_info(key);

    vistk::config::description_t const desc = boost::replace_all_copy(info->description, "\n", "\n  #   ");

    m_ostr << "  # Key: " << key << std::endl;

    m_ostr << "  # Description: " << desc << std::endl;

    vistk::config::value_t const& def = info->def;

    if (def.empty())
    {
      m_ostr << "  # No default value" << std::endl;
    }
    else
    {
      m_ostr << "  # Default value: " << def << std::endl;
    }

    vistk::config::key_t const resolved_key = name + vistk::config::block_sep + key;

    if (m_config->has_value(resolved_key))
    {
      vistk::config::value_t const cur_value = m_config->get_value<vistk::config::value_t>(resolved_key);

      m_ostr << "  # Current value: " << cur_value << std::endl;
    }
    else
    {
      m_ostr << "  # No current value" << std::endl;
    }
  }

  m_ostr << std::endl;

  m_visited.insert(name);
}

key_printer
::key_printer(std::ostream& ostr)
  : m_ostr(ostr)
{
}

key_printer
::~key_printer()
{
}

void
key_printer
::operator () (vistk::config_value_t const& config_value) const
{
  vistk::config_key_t const& key = config_value.key;
  vistk::config::value_t const& value = config_value.value;

  vistk::config::keys_t const& keys = key.key_path;
  vistk::config_key_options_t const& options = key.options;

  vistk::config::key_t const key_path = boost::join(keys, vistk::config::block_sep);

  boost::optional<vistk::config_flags_t> const& flags = options.flags;
  boost::optional<vistk::config_provider_t> const& provider = options.provider;

  m_ostr << "  " << vistk::config::block_sep << key_path;

  if (flags)
  {
    vistk::config_flag_t const flag_list = boost::join(*flags, ",");

    m_ostr << "[" << flag_list << "]";
  }

  if (provider)
  {
    m_ostr << "{" << *provider << "}";
  }

  m_ostr << " " << value << std::endl;
}
<commit_msg>Output proper names configuration blocks<commit_after>/*ckwg +5
 * Copyright 2012-2013 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include "helpers/pipeline_builder.h"
#include "helpers/tool_main.h"
#include "helpers/tool_usage.h"

#include <vistk/pipeline_util/pipe_declaration_types.h>

#include <vistk/pipeline/config.h>
#include <vistk/pipeline/modules.h>
#include <vistk/pipeline/pipeline.h>
#include <vistk/pipeline/pipeline_exception.h>
#include <vistk/pipeline/process.h>
#include <vistk/pipeline/process_cluster.h>
#include <vistk/pipeline/types.h>

#include <vistk/utilities/path.h>

#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/foreach.hpp>
#include <boost/variant.hpp>

#include <algorithm>
#include <iostream>
#include <iterator>
#include <set>
#include <stdexcept>
#include <string>

#include <cstdlib>

class config_printer
  : public boost::static_visitor<>
{
  public:
    config_printer(std::ostream& ostr, vistk::pipeline_t const& pipe, vistk::config_t const& conf);
    ~config_printer();

    void operator () (vistk::config_pipe_block const& config_block);
    void operator () (vistk::process_pipe_block const& process_block);
    void operator () (vistk::connect_pipe_block const& connect_block) const;

    void output_process_defaults();
  private:
    void print_config_value(vistk::config_value_t const& config_value) const;
    void output_process_by_name(vistk::process::name_t const& name, bool fatal_if_no_process);
    void output_process_block(vistk::process_t const& name, std::string const& kind);
    void output_process(vistk::process_t const& proc);

    typedef std::set<vistk::process::name_t> process_set_t;

    std::ostream& m_ostr;
    vistk::pipeline_t const m_pipe;
    vistk::config_t const m_config;
    process_set_t m_visited;
};

int
tool_main(int argc, char* argv[])
{
  vistk::load_known_modules();

  boost::program_options::options_description desc;
  desc
    .add(tool_common_options())
    .add(pipeline_common_options())
    .add(pipeline_input_options())
    .add(pipeline_output_options());

  boost::program_options::variables_map const vm = tool_parse(argc, argv, desc);

  pipeline_builder const builder(vm, desc);

  vistk::pipeline_t const pipe = builder.pipeline();
  vistk::config_t const config = builder.config();
  vistk::pipe_blocks const blocks = builder.blocks();

  if (!pipe)
  {
    std::cerr << "Error: Unable to bake pipeline" << std::endl;

    return EXIT_FAILURE;
  }

  std::ostream* postr;
  boost::filesystem::ofstream fout;

  vistk::path_t const opath = vm["output"].as<vistk::path_t>();

  if (opath == vistk::path_t("-"))
  {
    postr = &std::cout;
  }
  else
  {
    fout.open(opath);

    if (fout.bad())
    {
      std::cerr << "Error: Unable to open output file" << std::endl;

      return EXIT_FAILURE;
    }

    postr = &fout;
  }

  std::ostream& ostr = *postr;

  config_printer printer(ostr, pipe, config);

  std::for_each(blocks.begin(), blocks.end(), boost::apply_visitor(printer));

  printer.output_process_defaults();

  return EXIT_SUCCESS;
}

config_printer
::config_printer(std::ostream& ostr, vistk::pipeline_t const& pipe, vistk::config_t const& conf)
  : m_ostr(ostr)
  , m_pipe(pipe)
  , m_config(conf)
{
}

config_printer
::~config_printer()
{
}

class key_printer
{
  public:
    key_printer(std::ostream& ostr);
    ~key_printer();

    void operator () (vistk::config_value_t const& config_value) const;
  private:
    std::ostream& m_ostr;
};

static vistk::process::name_t denormalize_name(vistk::process::name_t const& name);

void
config_printer
::operator () (vistk::config_pipe_block const& config_block)
{
  vistk::config::keys_t const& keys = config_block.key;
  vistk::config_values_t const& values = config_block.values;

  vistk::config::key_t const key_path = boost::join(keys, vistk::config::block_sep);

  m_ostr << "config " << key_path << std::endl;

  key_printer const printer(m_ostr);

  std::for_each(values.begin(), values.end(), printer);

  vistk::process::name_t const denorm_name = denormalize_name(key_path);

  output_process_by_name(denorm_name, false);
}

static vistk::process::name_t normalize_name(vistk::process::name_t const& name);

void
config_printer
::operator () (vistk::process_pipe_block const& process_block)
{
  vistk::process::name_t const& name = process_block.name;
  vistk::process::type_t const& type = process_block.type;
  vistk::config_values_t const& values = process_block.config_values;

  m_ostr << "process " << name << std::endl;
  m_ostr << "  :: " << type << std::endl;

  key_printer const printer(m_ostr);

  std::for_each(values.begin(), values.end(), printer);

  output_process_by_name(name, true);
}

void
config_printer
::operator () (vistk::connect_pipe_block const& connect_block) const
{
  vistk::process::port_addr_t const& upstream_addr = connect_block.from;
  vistk::process::port_addr_t const& downstream_addr = connect_block.to;

  vistk::process::name_t const& upstream_name = upstream_addr.first;
  vistk::process::port_t const& upstream_port = upstream_addr.second;
  vistk::process::name_t const& downstream_name = downstream_addr.first;
  vistk::process::port_t const& downstream_port = downstream_addr.second;

  m_ostr << "connect from " << upstream_name << "." << upstream_port << std::endl;
  m_ostr << "        to   " << downstream_name << "." << downstream_port << std::endl;

  m_ostr << std::endl;
}

void
config_printer
::output_process_defaults()
{
  vistk::process::names_t const cluster_names = m_pipe->cluster_names();

  BOOST_FOREACH (vistk::process::name_t const& name, cluster_names)
  {
    if (m_visited.count(name))
    {
      continue;
    }

    vistk::process_cluster_t const cluster = m_pipe->cluster_by_name(name);
    vistk::process_t const proc = boost::static_pointer_cast<vistk::process>(cluster);

    static std::string const kind = "cluster";

    output_process_block(proc, kind);
  }

  vistk::process::names_t const process_names = m_pipe->process_names();

  BOOST_FOREACH (vistk::process::name_t const& name, process_names)
  {
    if (m_visited.count(name))
    {
      continue;
    }

    vistk::process_t const proc = m_pipe->process_by_name(name);

    static std::string const kind = "process";

    output_process_block(proc, kind);
  }
}

void
config_printer
::output_process_by_name(vistk::process::name_t const& name, bool fatal_if_no_process)
{
  vistk::process_t proc;

  if (!m_visited.count(name))
  {
    try
    {
      proc = m_pipe->process_by_name(name);
    }
    catch (vistk::no_such_process_exception const& /*e*/)
    {
      try
      {
        vistk::process_cluster_t const cluster = m_pipe->cluster_by_name(name);

        proc = boost::static_pointer_cast<vistk::process>(cluster);
      }
      catch (vistk::no_such_process_exception const& /*e*/)
      {
        if (fatal_if_no_process)
        {
          std::string const reason = "A process block did not result in a process being "
                                     "added to the pipeline: " + name;

          throw std::logic_error(reason);
        }
      }
    }
  }

  if (proc)
  {
    output_process(proc);
  }
  else
  {
    m_ostr << std::endl;
  }
}

void
config_printer
::output_process_block(vistk::process_t const& proc, std::string const& kind)
{
  vistk::process::name_t const name = proc->name();
  vistk::process::type_t const type = proc->type();
  vistk::process::name_t const norm_name = normalize_name(name);

  m_ostr << "# Defaults for \'" << name << "\' " << kind << ":" << std::endl;
  m_ostr << "config " << norm_name << std::endl;
  m_ostr << "#  :: " << type << std::endl;

  output_process(proc);
}

void
config_printer
::output_process(vistk::process_t const& proc)
{
  vistk::process::name_t const name = proc->name();
  vistk::config::keys_t const keys = proc->available_config();
  vistk::process::name_t const norm_name = normalize_name(name);

  BOOST_FOREACH (vistk::config::key_t const& key, keys)
  {
    if (boost::starts_with(key, "_"))
    {
      continue;
    }

    m_ostr << std::endl;

    vistk::process::conf_info_t const& info = proc->config_info(key);

    vistk::config::description_t const desc = boost::replace_all_copy(info->description, "\n", "\n  #   ");

    m_ostr << "  # Key: " << key << std::endl;

    m_ostr << "  # Description: " << desc << std::endl;

    vistk::config::value_t const& def = info->def;

    if (def.empty())
    {
      m_ostr << "  # No default value" << std::endl;
    }
    else
    {
      m_ostr << "  # Default value: " << def << std::endl;
    }

    vistk::config::key_t const resolved_key = norm_name + vistk::config::block_sep + key;

    if (m_config->has_value(resolved_key))
    {
      vistk::config::value_t const cur_value = m_config->get_value<vistk::config::value_t>(resolved_key);

      m_ostr << "  # Current value: " << cur_value << std::endl;
    }
    else
    {
      m_ostr << "  # No current value" << std::endl;
    }
  }

  m_ostr << std::endl;

  m_visited.insert(name);
}

key_printer
::key_printer(std::ostream& ostr)
  : m_ostr(ostr)
{
}

key_printer
::~key_printer()
{
}

void
key_printer
::operator () (vistk::config_value_t const& config_value) const
{
  vistk::config_key_t const& key = config_value.key;
  vistk::config::value_t const& value = config_value.value;

  vistk::config::keys_t const& keys = key.key_path;
  vistk::config_key_options_t const& options = key.options;

  vistk::config::key_t const key_path = boost::join(keys, vistk::config::block_sep);

  boost::optional<vistk::config_flags_t> const& flags = options.flags;
  boost::optional<vistk::config_provider_t> const& provider = options.provider;

  m_ostr << "  " << vistk::config::block_sep << key_path;

  if (flags)
  {
    vistk::config_flag_t const flag_list = boost::join(*flags, ",");

    m_ostr << "[" << flag_list << "]";
  }

  if (provider)
  {
    m_ostr << "{" << *provider << "}";
  }

  m_ostr << " " << value << std::endl;
}

vistk::process::name_t
denormalize_name(vistk::process::name_t const& name)
{
  vistk::process::name_t denorm_name;

  std::replace_copy_if(name.begin(), name.end(),
                       std::back_inserter(denorm_name),
                       boost::is_any_of(":"), '/');

  return denorm_name;
}

vistk::process::name_t
normalize_name(vistk::process::name_t const& name)
{
  vistk::process::name_t norm_name;

  std::replace_copy_if(name.begin(), name.end(),
                       std::back_inserter(norm_name),
                       boost::is_any_of("/"), ':');

  return norm_name;
}
<|endoftext|>


<commit_before>#include <ros/console.h>
#include <string>

#include <tr_hub_parser/RangeArray.h>
#include <tr_hub_parser/tr_evo_hub_parser.h>

namespace tr_hub_parser {

Tr_hub_parser::Tr_hub_parser() {

    // Get parameters
    ros::NodeHandle private_node_handle_("~");
    private_node_handle_.param("portname", portname_,
                               std::string("/dev/ttyACM0"));
    // Publishers
    range_publisher_ = nh_.advertise<tr_hub_parser::RangeArray>("tr_hub_parser", 8);

    // Serial Port init
    serial_port_ = new SerialPort();
    if (!serial_port_->connect(portname_)) {
      ROS_ERROR("Could not open : %s ", portname_.c_str());
      ros::shutdown();
      return;
    }
    else {
      serial_data_callback_function_ =
          boost::bind(&Tr_hub_parser::serialDataCallback, this, _1);
      serial_port_->setSerialCallbackFunction(&serial_data_callback_function_);
    }

    // Output loaded parameters to console for double checking
    ROS_INFO("[%s] is up and running with the following parameters:",
             ros::this_node::getName().c_str());
    ROS_INFO("[%s] portname: %s", ros::this_node::getName().c_str(),
             portname_.c_str());

    ns_ = ros::this_node::getNamespace();
    ns_ = ros::names::clean(ns_);
    std::string str = ns_.c_str();
    ROS_INFO("node namespace: [%s]", ns_.c_str());

    //Initialize local parameters and measurement array
    field_of_view = 0.0593;
    max_range = 14.0;
    min_range = 0.2;
    number_of_sensor = 8;
    frame_id = "base_range_";

    // Initialize rangeArray
    for (size_t i=0; i < number_of_sensor; i++) {
     sensor_msgs::Range range;
     range.field_of_view = field_of_view;
     range.max_range = max_range;
     range.min_range = min_range;
     range.radiation_type = sensor_msgs::Range::INFRARED;
     range.range = 0.0;
     range.header.frame_id =
         ros::names::append(ns_, frame_id + boost::lexical_cast<std::string>(i));

     measure.ranges.push_back(range);
    }

    // This line is needed to start measurements on the hub
    setMode(ENABLE_CMD, 5);
    setMode(BINARY_MODE, 4);
    setMode(CROSSTALK_MODE, 4);
    setMode(RATE_700, 5);

    // Dynamic reconfigure
    dyn_param_server_callback_function_ =
        boost::bind(&Tr_hub_parser::dynParamCallback, this, _1, _2);
    dyn_param_server_.setCallback(dyn_param_server_callback_function_);
  }

  Tr_hub_parser::~Tr_hub_parser() {}

  uint8_t crc8(uint8_t *p, uint8_t len) {
    uint16_t i;
    uint16_t crc = 0x0;

    while (len--) {
      i = (crc ^ *p++) & 0xFF;
      crc = (crc_table[i] ^ (crc << 8)) & 0xFF;
    }
    return crc & 0xFF;
  }

  float two_chars_to_float(uint8_t c1, uint8_t c2){
    int16_t current_range = c1 << 8;
    current_range |= c2;

    float res = (float)current_range;
    return res;
  }

  void Tr_hub_parser::setMode(const char *c, int length) {
    serial_port_->sendChar(c, length);
  }

  void Tr_hub_parser::dynParamCallback(
      const tr_hub_parser::Tr_hub_parserConfig &config, uint32_t level) {
    if (config.Mode == tr_hub_parser::Tr_hub_parser_Fast) {
      // setMode(FAST_MODE);
    }

    if (config.Mode == tr_hub_parser::Tr_hub_parser_Precise) {
      // setMode(PRECISE_MODE);
    }

    if (config.Mode == tr_hub_parser::Tr_hub_parser_Outdoor) {
      // setMode(OUTDOOR_MODE);
    }
  }

  void Tr_hub_parser::serialDataCallback(uint8_t single_character) {
    static uint8_t input_buffer[BUFFER_SIZE];
    static int buffer_ctr = 0;
    static int seq_ctr = 0;

    if (single_character == 'T' && buffer_ctr == 0) {
      // Waiting for T
      input_buffer[buffer_ctr++] = single_character;
      return;
    }
    else if (single_character == 'H' && buffer_ctr == 1) {
      // Waiting for H after a T
      input_buffer[buffer_ctr++] = single_character;
      return;
    }

    if (buffer_ctr > 1 && buffer_ctr < RANGES_FRAME_LENGTH) {
      input_buffer[buffer_ctr++] = single_character;
      return;
    }

    if (buffer_ctr == RANGES_FRAME_LENGTH) {
      // end of feed, calculate
      input_buffer[buffer_ctr++] = single_character;
      int16_t crc = crc8(input_buffer, 19);

      if (crc == input_buffer[RANGE_CRC_POS]) {
          ROS_DEBUG("Frame: %s ", input_buffer);

          for (size_t i=0; i < measure.ranges.size(); i++) {
            measure.ranges.at(i).header.stamp = ros::Time::now();
            measure.ranges.at(i).header.seq = seq_ctr++;

            // Doesn't go out of range because of fixed buffer size as long as the number of sensor is not above 8
            float float_range = two_chars_to_float(input_buffer[2 * (i + 1)],input_buffer[2 * (i + 1) + 1]);

            if ((float_range * 0.001 < min_range) && (float_range > 0)) { //check for hardware cut-off
              float_range = min_range;
            } else if ((float_range * 0.001 > max_range) || (float_range < 0)) { //software cut-off should be adapted to sensor
              float_range = -1.0;
            } else {
              float_range = float_range * 0.001;
            }
            measure.ranges.at(i).range = float_range;
          }
          range_publisher_.publish(measure);
      } else {
        ROS_DEBUG("[%s] crc missmatch", ros::this_node::getName().c_str());
      }
    } else {
        ROS_DEBUG("[%s] : Buffer overflow, resetting buffer without "
                  "evaluating data",
                  ros::this_node::getName().c_str());
    }

    // resetting buffer and ctr
    buffer_ctr = 0;
    bzero(&input_buffer, BUFFER_SIZE);
  }

  }

  int main(int argc, char **argv) {
    ros::init(argc, argv, "tr_hub_parser_node");
    tr_hub_parser::Tr_hub_parser tr_hub_parser_node;
    ros::spin();

    return 0;
  }
<commit_msg>Enhance parsing method<commit_after>#include <ros/console.h>
#include <string>

#include <tr_hub_parser/RangeArray.h>
#include <tr_hub_parser/tr_evo_hub_parser.h>

namespace tr_hub_parser {

Tr_hub_parser::Tr_hub_parser() {

    // Get parameters
    ros::NodeHandle private_node_handle_("~");
    private_node_handle_.param("portname", portname_,
                               std::string("/dev/ttyACM0"));
    // Publishers
    range_publisher_ = nh_.advertise<tr_hub_parser::RangeArray>("tr_hub_parser", 8);

    // Serial Port init
    serial_port_ = new SerialPort();
    if (!serial_port_->connect(portname_)) {
      ROS_ERROR("Could not open : %s ", portname_.c_str());
      ros::shutdown();
      return;
    }
    else {
      serial_data_callback_function_ =
          boost::bind(&Tr_hub_parser::serialDataCallback, this, _1);
      serial_port_->setSerialCallbackFunction(&serial_data_callback_function_);
    }

    // Output loaded parameters to console for double checking
    ROS_INFO("[%s] is up and running with the following parameters:",
             ros::this_node::getName().c_str());
    ROS_INFO("[%s] portname: %s", ros::this_node::getName().c_str(),
             portname_.c_str());

    ns_ = ros::this_node::getNamespace();
    ns_ = ros::names::clean(ns_);
    std::string str = ns_.c_str();
    ROS_INFO("node namespace: [%s]", ns_.c_str());

    //Initialize local parameters and measurement array
    field_of_view = 0.0593;
    max_range = 14.0;
    min_range = 0.2;
    number_of_sensor = 8;
    frame_id = "base_range_";

    // Initialize rangeArray
    for (size_t i=0; i < number_of_sensor; i++) {
     sensor_msgs::Range range;
     range.field_of_view = field_of_view;
     range.max_range = max_range;
     range.min_range = min_range;
     range.radiation_type = sensor_msgs::Range::INFRARED;
     range.range = 0.0;
     range.header.frame_id =
         ros::names::append(ns_, frame_id + boost::lexical_cast<std::string>(i));

     measure.ranges.push_back(range);
    }

    // This line is needed to start measurements on the hub
    setMode(ENABLE_CMD, 5);
    setMode(BINARY_MODE, 4);
    setMode(CROSSTALK_MODE, 4);
    setMode(RATE_700, 5);

    // Dynamic reconfigure
    dyn_param_server_callback_function_ =
        boost::bind(&Tr_hub_parser::dynParamCallback, this, _1, _2);
    dyn_param_server_.setCallback(dyn_param_server_callback_function_);
  }

  Tr_hub_parser::~Tr_hub_parser() {}

  uint8_t crc8(uint8_t *p, uint8_t len) {
    uint16_t i;
    uint16_t crc = 0x0;

    while (len--) {
      i = (crc ^ *p++) & 0xFF;
      crc = (crc_table[i] ^ (crc << 8)) & 0xFF;
    }
    return crc & 0xFF;
  }

  float two_chars_to_float(uint8_t c1, uint8_t c2){
    int16_t current_range = c1 << 8;
    current_range |= c2;

    float res = (float)current_range;
    return res;
  }

  void Tr_hub_parser::setMode(const char *c, int length) {
    serial_port_->sendChar(c, length);
  }

  void Tr_hub_parser::dynParamCallback(
      const tr_hub_parser::Tr_hub_parserConfig &config, uint32_t level) {
    if (config.Mode == tr_hub_parser::Tr_hub_parser_Fast) {
      // setMode(FAST_MODE);
    }

    if (config.Mode == tr_hub_parser::Tr_hub_parser_Precise) {
      // setMode(PRECISE_MODE);
    }

    if (config.Mode == tr_hub_parser::Tr_hub_parser_Outdoor) {
      // setMode(OUTDOOR_MODE);
    }
  }

  void Tr_hub_parser::serialDataCallback(uint8_t single_character) {
    static uint8_t input_buffer[BUFFER_SIZE];
    static int buffer_ctr = 0;
    static int seq_ctr = 0;

    ROS_DEBUG("Buffer of size %d : %s | current char : %c", buffer_ctr, input_buffer, (char)single_character);

    if (single_character == 'T' && buffer_ctr == 0) {
      // Waiting for T
      input_buffer[buffer_ctr++] = single_character;
      return;
    }
    else if (single_character == 'H' && buffer_ctr == 1) {
      // Waiting for H after a T
      input_buffer[buffer_ctr++] = single_character;
      return;
    }

    // Gathering after-header range data
    if (buffer_ctr > 1 && buffer_ctr < RANGES_FRAME_LENGTH) {
      input_buffer[buffer_ctr++] = single_character;
      return;
    }
    else if (buffer_ctr == RANGES_FRAME_LENGTH) {
      //Processing full range frame
      int16_t crc = crc8(input_buffer, 19);

      if (crc == input_buffer[RANGE_CRC_POS]) {
          ROS_DEBUG("Frame of size %d : %s ", buffer_ctr, input_buffer);

          for (size_t i=0; i < measure.ranges.size(); i++) {
            measure.ranges.at(i).header.stamp = ros::Time::now();
            measure.ranges.at(i).header.seq = seq_ctr++;

            // Doesn't go out of range because of fixed buffer size as long as the number of sensor is not above 8
            float float_range = two_chars_to_float(input_buffer[2 * (i + 1)],input_buffer[2 * (i + 1) + 1]);

            if ((float_range * 0.001 < min_range) && (float_range > 0)) { //check for hardware cut-off
              float_range = min_range;
            } else if ((float_range * 0.001 > max_range) || (float_range < 0)) { //software cut-off should be adapted to sensor
              float_range = -1.0;
            } else {
              float_range = float_range * 0.001;
            }
            measure.ranges.at(i).range = float_range;
          }
          range_publisher_.publish(measure);
      } else {
        ROS_DEBUG("[%s] crc missmatch", ros::this_node::getName().c_str());
      }
    } else if (buffer_ctr > RANGES_FRAME_LENGTH){
        ROS_DEBUG("[%s] : Buffer overflow, resetting buffer without "
                  "evaluating data",
                  ros::this_node::getName().c_str());
    }
    // resetting buffer and ctr
    buffer_ctr = 0;
    bzero(&input_buffer, BUFFER_SIZE);

    // Appending current char to hook next frame
    input_buffer[buffer_ctr++] = single_character;
  }

  }

  int main(int argc, char **argv) {
    ros::init(argc, argv, "tr_hub_parser_node");
    tr_hub_parser::Tr_hub_parser tr_hub_parser_node;
    ros::spin();

    return 0;
  }
<|endoftext|>


<commit_before>/*
* Copyright 2008 Free Software Foundation, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program 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 Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "Sockets.h"
#include "Threads.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

static const int gNumToSend = 10;

static void sigalarm_handler(int foo)
{
	printf("FAIL: test did not run successfully\n");
	exit(EXIT_FAILURE);
}

void *testReaderIP(void *param)
{
	UDPSocket *readSocket = (UDPSocket *)param;
	readSocket->nonblocking();
	int rc = 0;
	while (rc<gNumToSend) {
		char buf[MAX_UDP_LENGTH];
		int count = readSocket->read(buf, MAX_UDP_LENGTH);
		if (count>0) {
			CERR("read: " << buf);
			rc++;
		} else {
			sleep(2);
		}
	}
	return NULL;
}

int main(int argc, char * argv[] )
{
  int count;

  if (signal(SIGALRM, sigalarm_handler) == SIG_ERR) {
    perror("signal");
    exit(EXIT_FAILURE);
  }

  /* If the test takes longer than 2*gNumToSend seconds, abort it */
  alarm(2* gNumToSend);

  UDPSocket readSocket("127.0.0.1", 0);
  UDPSocket socket1("127.0.0.1", 0, "localhost", readSocket.port());

  CERR("socket1: " << socket1.port() << ", readSocket: " << readSocket.port());

  Thread readerThreadIP;
  readerThreadIP.start(testReaderIP, &readSocket);

  // give the readers time to open
  sleep(1);

  for (int i=0; i<gNumToSend; i++) {
    CERR("write");
    count = socket1.write("Hello IP land");
    if (count < 0) {
      COUT("FAIL: write");
      exit(EXIT_FAILURE);
    }
    sleep(1);
  }

  readerThreadIP.join();

  printf("Done\n");
}

// vim: ts=4 sw=4
<commit_msg>tests: null-terminate buffer<commit_after>/*
* Copyright 2008 Free Software Foundation, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program 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 Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "Sockets.h"
#include "Threads.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

static const int gNumToSend = 10;

static void sigalarm_handler(int foo)
{
	printf("FAIL: test did not run successfully\n");
	exit(EXIT_FAILURE);
}

void *testReaderIP(void *param)
{
	UDPSocket *readSocket = (UDPSocket *)param;
	readSocket->nonblocking();
	int rc = 0;
	while (rc<gNumToSend) {
		char buf[MAX_UDP_LENGTH] = { 0 };
		int count = readSocket->read(buf, MAX_UDP_LENGTH);
		if (count>0) {
			CERR("read: " << buf);
			rc++;
		} else {
			sleep(2);
		}
	}
	return NULL;
}

int main(int argc, char * argv[] )
{
  int count;

  if (signal(SIGALRM, sigalarm_handler) == SIG_ERR) {
    perror("signal");
    exit(EXIT_FAILURE);
  }

  /* If the test takes longer than 2*gNumToSend seconds, abort it */
  alarm(2* gNumToSend);

  UDPSocket readSocket("127.0.0.1", 0);
  UDPSocket socket1("127.0.0.1", 0, "localhost", readSocket.port());

  CERR("socket1: " << socket1.port() << ", readSocket: " << readSocket.port());

  Thread readerThreadIP;
  readerThreadIP.start(testReaderIP, &readSocket);

  // give the readers time to open
  sleep(1);

  for (int i=0; i<gNumToSend; i++) {
    CERR("write");
    count = socket1.write("Hello IP land");
    if (count < 0) {
      COUT("FAIL: write");
      exit(EXIT_FAILURE);
    }
    sleep(1);
  }

  readerThreadIP.join();

  printf("Done\n");
}

// vim: ts=4 sw=4
<|endoftext|>


<commit_before>#include <Core/Geometry/MeshPrimitives.hpp>
#include <Core/Geometry/TopologicalMesh.hpp>
#include <Core/Geometry/TriangleMesh.hpp>
#include <Tests.hpp>

#include <OpenMesh/Tools/Subdivider/Uniform/CatmullClarkT.hh>
#include <OpenMesh/Tools/Subdivider/Uniform/LoopT.hh>

#include <OpenMesh/Tools/Decimater/DecimaterT.hh>
#include <OpenMesh/Tools/Decimater/ModQuadricT.hh>
namespace Ra {
namespace Testing {

bool isSameMesh( Ra::Core::Geometry::TriangleMesh& meshOne,
                 Ra::Core::Geometry::TriangleMesh& meshTwo ) {

    using Ra::Core::Vector3;
    using Ra::Core::Geometry::TopologicalMesh;
    using Ra::Core::Geometry::TriangleMesh;

    bool result = true;
    int i = 0;
    // Check length
    if ( meshOne.vertices().size() != meshTwo.vertices().size() )
        return false;
    if ( meshOne.normals().size() != meshTwo.normals().size() )
        return false;
    if ( meshOne.m_triangles.size() != meshTwo.m_triangles.size() )
        return false;

    // Check triangles
    std::vector<Ra::Core::Vector3> stackVertices;
    std::vector<Ra::Core::Vector3> stackNormals;

    i = 0;
    while ( result && i < meshOne.m_triangles.size() )
    {
        std::vector<Ra::Core::Vector3>::iterator it;
        stackVertices.clear();
        stackVertices.push_back( meshOne.vertices()[meshOne.m_triangles[i][0]] );
        stackVertices.push_back( meshOne.vertices()[meshOne.m_triangles[i][1]] );
        stackVertices.push_back( meshOne.vertices()[meshOne.m_triangles[i][2]] );

        stackNormals.clear();
        stackNormals.push_back( meshOne.normals()[meshOne.m_triangles[i][0]] );
        stackNormals.push_back( meshOne.normals()[meshOne.m_triangles[i][1]] );
        stackNormals.push_back( meshOne.normals()[meshOne.m_triangles[i][2]] );

        for ( int j = 0; j < 3; ++j )
        {
            it = find( stackVertices.begin(), stackVertices.end(),
                       meshTwo.vertices()[meshTwo.m_triangles[i][j]] );
            if ( it != stackVertices.end() )
            {
                stackVertices.erase( it );
            } else
            { result = false; }
        }

        for ( int j = 0; j < 3; ++j )
        {
            it = find( stackNormals.begin(), stackNormals.end(),
                       meshTwo.normals()[meshTwo.m_triangles[i][j]] );
            if ( it != stackNormals.end() )
            {
                stackNormals.erase( it );
            } else
            { result = false; }
        }

        ++i;
    }
    return result;
}

void run() {
    using Ra::Core::Vector3;
    using Ra::Core::Geometry::TopologicalMesh;
    using Ra::Core::Geometry::TriangleMesh;

    using Catmull =
        OpenMesh::Subdivider::Uniform::CatmullClarkT<Ra::Core::Geometry::TopologicalMesh>;
    using Loop = OpenMesh::Subdivider::Uniform::LoopT<Ra::Core::Geometry::TopologicalMesh>;

    using Decimater = OpenMesh::Decimater::DecimaterT<Ra::Core::Geometry::TopologicalMesh>;
    using HModQuadric =
        OpenMesh::Decimater::ModQuadricT<Ra::Core::Geometry::TopologicalMesh>::Handle;

    TriangleMesh newMesh;
    TriangleMesh mesh;
    TopologicalMesh topologicalMesh;

    // Test for close mesh
    mesh = Ra::Core::Geometry::makeBox();
    topologicalMesh = TopologicalMesh( mesh );
    newMesh = topologicalMesh.toTriangleMesh();
    RA_VERIFY( isSameMesh( mesh, newMesh ), "Conversion to topological box mesh" );

    mesh = Ra::Core::Geometry::makeSharpBox();
    topologicalMesh = TopologicalMesh( mesh );
    newMesh = topologicalMesh.toTriangleMesh();
    RA_VERIFY( isSameMesh( mesh, newMesh ), "Conversion to topological sharp box mesh" );

    // Test for mesh with boundaries
    mesh = Ra::Core::Geometry::makePlaneGrid( 2, 2 );
    topologicalMesh = TopologicalMesh( mesh );
    newMesh = topologicalMesh.toTriangleMesh();
    RA_VERIFY( isSameMesh( mesh, newMesh ), "Conversion to topological grid mesh" );

    mesh = Ra::Core::Geometry::makeCylinder( Vector3( 0, 0, 0 ), Vector3( 0, 0, 1 ), 1 );
    topologicalMesh = TopologicalMesh( mesh );
    newMesh = topologicalMesh.toTriangleMesh();
    RA_VERIFY( isSameMesh( mesh, newMesh ), "Conversion to topological cylinder mesh" );

    mesh = Ra::Core::Geometry::makeBox();
    topologicalMesh = TopologicalMesh( mesh );

    for ( TopologicalMesh::ConstVertexIter v_it = topologicalMesh.vertices_begin();
          v_it != topologicalMesh.vertices_end(); ++v_it )
    {
        topologicalMesh.set_normal(
            *v_it, TopologicalMesh::Normal( Scalar( 1. ), Scalar( 0. ), Scalar( 0. ) ) );
    }

    for ( TopologicalMesh::ConstVertexIter v_it = topologicalMesh.vertices_begin();
          v_it != topologicalMesh.vertices_end(); ++v_it )
    {
        topologicalMesh.propagate_normal_to_halfedges( *v_it );
    }

    {
        newMesh = topologicalMesh.toTriangleMesh();
        bool check1 = true;
        bool check2 = true;
        for ( auto n : newMesh.normals() )
        {
            if ( !Ra::Core::Math::areApproxEqual(
                     n.dot( Vector3( Scalar( 1. ), Scalar( 0. ), Scalar( 0. ) ) ), Scalar( 1. ) ) )
            {
                check1 = false;
            }
            if ( n.dot( Vector3( Scalar( 0.5 ), Scalar( 0. ), Scalar( 0. ) ) ) > Scalar( 0.8 ) )
            {
                check2 = false;
            }
        }
        RA_VERIFY( check1 && check2, "Set normal to topo vertex and apply them to halfedge" );
    }
}
} // namespace Testing
} // namespace Ra

int main( int argc, const char** argv ) {
    using namespace Ra;

    if ( !Testing::init_testing( 1, argv ) )
    {
        return EXIT_FAILURE;
    }

#pragma omp parallel for
    for ( int i = 0; i < Testing::g_repeat; ++i )
    {
        CALL_SUBTEST( ( Testing::run() ) );
    }

    return EXIT_SUCCESS;
}
<commit_msg>Add test for attrib size in TopologicalMesh ;<commit_after>#include <Core/Geometry/MeshPrimitives.hpp>
#include <Core/Geometry/TopologicalMesh.hpp>
#include <Core/Geometry/TriangleMesh.hpp>
#include <Tests.hpp>

#include <OpenMesh/Tools/Subdivider/Uniform/CatmullClarkT.hh>
#include <OpenMesh/Tools/Subdivider/Uniform/LoopT.hh>

#include <OpenMesh/Tools/Decimater/DecimaterT.hh>
#include <OpenMesh/Tools/Decimater/ModQuadricT.hh>
namespace Ra {
namespace Testing {

bool isSameMesh( Ra::Core::Geometry::TriangleMesh& meshOne,
                 Ra::Core::Geometry::TriangleMesh& meshTwo ) {

    using Ra::Core::Vector3;
    using Ra::Core::Geometry::TopologicalMesh;
    using Ra::Core::Geometry::TriangleMesh;

    bool result = true;
    int i = 0;
    // Check length
    if ( meshOne.vertices().size() != meshTwo.vertices().size() )
        return false;
    if ( meshOne.normals().size() != meshTwo.normals().size() )
        return false;
    if ( meshOne.m_triangles.size() != meshTwo.m_triangles.size() )
        return false;

    // Check triangles
    std::vector<Ra::Core::Vector3> stackVertices;
    std::vector<Ra::Core::Vector3> stackNormals;

    i = 0;
    while ( result && i < meshOne.m_triangles.size() )
    {
        std::vector<Ra::Core::Vector3>::iterator it;
        stackVertices.clear();
        stackVertices.push_back( meshOne.vertices()[meshOne.m_triangles[i][0]] );
        stackVertices.push_back( meshOne.vertices()[meshOne.m_triangles[i][1]] );
        stackVertices.push_back( meshOne.vertices()[meshOne.m_triangles[i][2]] );

        stackNormals.clear();
        stackNormals.push_back( meshOne.normals()[meshOne.m_triangles[i][0]] );
        stackNormals.push_back( meshOne.normals()[meshOne.m_triangles[i][1]] );
        stackNormals.push_back( meshOne.normals()[meshOne.m_triangles[i][2]] );

        for ( int j = 0; j < 3; ++j )
        {
            it = find( stackVertices.begin(), stackVertices.end(),
                       meshTwo.vertices()[meshTwo.m_triangles[i][j]] );
            if ( it != stackVertices.end() )
            {
                stackVertices.erase( it );
            } else
            { result = false; }
        }

        for ( int j = 0; j < 3; ++j )
        {
            it = find( stackNormals.begin(), stackNormals.end(),
                       meshTwo.normals()[meshTwo.m_triangles[i][j]] );
            if ( it != stackNormals.end() )
            {
                stackNormals.erase( it );
            } else
            { result = false; }
        }

        ++i;
    }
    return result;
}

void run() {
    using Ra::Core::Vector3;
    using Ra::Core::Geometry::TopologicalMesh;
    using Ra::Core::Geometry::TriangleMesh;

    using Catmull =
        OpenMesh::Subdivider::Uniform::CatmullClarkT<Ra::Core::Geometry::TopologicalMesh>;
    using Loop = OpenMesh::Subdivider::Uniform::LoopT<Ra::Core::Geometry::TopologicalMesh>;

    using Decimater = OpenMesh::Decimater::DecimaterT<Ra::Core::Geometry::TopologicalMesh>;
    using HModQuadric =
        OpenMesh::Decimater::ModQuadricT<Ra::Core::Geometry::TopologicalMesh>::Handle;

    TriangleMesh newMesh;
    TriangleMesh mesh;
    TopologicalMesh topologicalMesh;

    // Test for close mesh
    mesh = Ra::Core::Geometry::makeBox();
    topologicalMesh = TopologicalMesh( mesh );
    newMesh = topologicalMesh.toTriangleMesh();
    RA_VERIFY( isSameMesh( mesh, newMesh ), "Conversion to topological box mesh" );

    mesh = Ra::Core::Geometry::makeSharpBox();
    topologicalMesh = TopologicalMesh( mesh );
    newMesh = topologicalMesh.toTriangleMesh();
    RA_VERIFY( isSameMesh( mesh, newMesh ), "Conversion to topological sharp box mesh" );

    // Test for mesh with boundaries
    mesh = Ra::Core::Geometry::makePlaneGrid( 2, 2 );
    topologicalMesh = TopologicalMesh( mesh );
    newMesh = topologicalMesh.toTriangleMesh();
    RA_VERIFY( isSameMesh( mesh, newMesh ), "Conversion to topological grid mesh" );

    mesh = Ra::Core::Geometry::makeCylinder( Vector3( 0, 0, 0 ), Vector3( 0, 0, 1 ), 1 );
    topologicalMesh = TopologicalMesh( mesh );
    newMesh = topologicalMesh.toTriangleMesh();
    RA_VERIFY( isSameMesh( mesh, newMesh ), "Conversion to topological cylinder mesh" );

    // Test skip empty attributes
    mesh.addAttrib<float>( "empty" );
    topologicalMesh = TopologicalMesh( mesh );
    newMesh = topologicalMesh.toTriangleMesh();
    RA_VERIFY( !newMesh.hasAttrib( "empty" ), "TopologicalMesh skip empty attributes" );

    // Test normals
    mesh = Ra::Core::Geometry::makeBox();
    topologicalMesh = TopologicalMesh( mesh );

    for ( TopologicalMesh::ConstVertexIter v_it = topologicalMesh.vertices_begin();
          v_it != topologicalMesh.vertices_end(); ++v_it )
    {
        topologicalMesh.set_normal(
            *v_it, TopologicalMesh::Normal( Scalar( 1. ), Scalar( 0. ), Scalar( 0. ) ) );
    }

    for ( TopologicalMesh::ConstVertexIter v_it = topologicalMesh.vertices_begin();
          v_it != topologicalMesh.vertices_end(); ++v_it )
    {
        topologicalMesh.propagate_normal_to_halfedges( *v_it );
    }

    {
        newMesh = topologicalMesh.toTriangleMesh();
        bool check1 = true;
        bool check2 = true;
        for ( auto n : newMesh.normals() )
        {
            if ( !Ra::Core::Math::areApproxEqual(
                     n.dot( Vector3( Scalar( 1. ), Scalar( 0. ), Scalar( 0. ) ) ), Scalar( 1. ) ) )
            {
                check1 = false;
            }
            if ( n.dot( Vector3( Scalar( 0.5 ), Scalar( 0. ), Scalar( 0. ) ) ) > Scalar( 0.8 ) )
            {
                check2 = false;
            }
        }
        RA_VERIFY( check1 && check2, "Set normal to topo vertex and apply them to halfedge" );
    }
}
} // namespace Testing
} // namespace Ra

int main( int argc, const char** argv ) {
    using namespace Ra;

    if ( !Testing::init_testing( 1, argv ) )
    {
        return EXIT_FAILURE;
    }

#pragma omp parallel for
    for ( int i = 0; i < Testing::g_repeat; ++i )
    {
        CALL_SUBTEST( ( Testing::run() ) );
    }

    return EXIT_SUCCESS;
}
<|endoftext|>