<commit_before>/* -------------------------------------------------------------------------- *
 *                     OpenSim:  SimpleOptimizationExample.cpp                      *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2012 Stanford University and the Authors                *
 * Author(s): Ayman Habib                                                *
 *                                                                            *
 * 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.                                             *
 * -------------------------------------------------------------------------- */

/*
 * Example of an OpenSim program that tries to find the elbow flexion angle that maximizes
 * the muscle moment arm of BICshort in the Arm26 model.
 */

//==============================================================================
//==============================================================================
#include <OpenSim/OpenSim.h>
#include <ctime>  // clock(), clock_t, CLOCKS_PER_SEC

using namespace OpenSim;
using namespace SimTK;
using namespace std;

// step count for troubleshooting
int stepCount = 0;

double bestSoFar = Infinity;

class ExampleOptimizationSystem : public OptimizerSystem {
   public:

       /* Constructor class. Parameters passed are accessed in the objectiveFunc() class. */
       ExampleOptimizationSystem(int numParameters, State& s, Model& aModel):
             numKnobs(numParameters), OptimizerSystem(numParameters), si(s), osimModel(aModel){}

    int objectiveFunc(  const Vector &newControls, bool new_coefficients, Real& f ) const override {

        // make a copy of out initial states
        State s = si;

        // Update the coordinate value of r_elbow_flex
        OpenSim::Coordinate& elbowFlexCoord = osimModel.updCoordinateSet().get("r_elbow_flex");
        elbowFlexCoord.setValue(s, newControls[0]);
        // Now equilibrate muscles at this configuration
        const Set<Muscle> &muscleSet = osimModel.getMuscles();
        // Make sure other muscle states are initialized the same with 1.0 activation, 0.1 fiberLength followed by equilibrium computation
        for(int i=0; i< muscleSet.getSize(); i++ ){
            muscleSet[i].setActivation(s, 1.0);
            const ActivationFiberLengthMuscle* afl = ActivationFiberLengthMuscle::safeDownCast(&muscleSet[i]);
            if (afl) afl->setFiberLength(s, .1);
        }
        // Make sure the muscles states are in equilibrium
        osimModel.equilibrateMuscles(s);

        const OpenSim::Muscle& bicShort = osimModel.getMuscles().get("BICshort");
        // Compute moment arm of BICshort, flip sign since the optimizer tries to minimize rather than maximize
        f = -bicShort.computeMomentArm(s, elbowFlexCoord);

        stepCount++;

        if( f < bestSoFar){
            bestSoFar = f;
            cout << "\nobjective evaluation #: " << stepCount << " elbow flexion angle = " << newControls[0]*SimTK_RADIAN_TO_DEGREE <<  " BICshort moment arm  = " << -f << std::endl;
        }

      return(0);

   }

private:
    int numKnobs;
    State& si;
    Model& osimModel;
 };

//______________________________________________________________________________
/**
 * Define an optimization problem that finds a set of muscle controls to maximize
 * the forward velocity of the forearm/hand segment mass center.
 */
int main()
{
    try {
        std::clock_t startTime = std::clock();

        // Create a new OpenSim model
        // Similar to arm26 model but without wrapping surfaces for better performance
        Model osimModel("Arm26_Optimize.osim");

        // Initialize the system and get the state representing the state system
        State& si = osimModel.initSystem();

        // initialize the starting shoulder angle
        const CoordinateSet& coords = osimModel.getCoordinateSet();
        coords.get("r_shoulder_elev").setValue(si, 0.0);

        // Set the initial muscle activations
        const Set<Muscle> &muscleSet = osimModel.getMuscles();
        for(int i=0; i< muscleSet.getSize(); i++ ){
            muscleSet[i].setActivation(si, 1.0);
            const ActivationFiberLengthMuscle* afl = ActivationFiberLengthMuscle::safeDownCast(&muscleSet[i]);
            afl->setFiberLength(si, .1);
        }
        OpenSim::Coordinate& elbowFlexCoord = osimModel.updCoordinateSet().get("r_elbow_flex");
        elbowFlexCoord.setValue(si, 1.0);
        //osimModel.getMultibodySystem().realize(si, Stage::Velocity);
        // Make sure the muscles states are in equilibrium
        osimModel.equilibrateMuscles(si);

        // Initialize the optimizer system we've defined.
        ExampleOptimizationSystem sys(1, si, osimModel);
        Real f = NaN;

        /* Define initial values and bounds for the controls to optimize */

        Vector controls(1, 1.0); // 1 radian for default value
        Vector lower_bounds(1, elbowFlexCoord.getRangeMin());
        Vector upper_bounds(1, elbowFlexCoord.getRangeMax());

        sys.setParameterLimits( lower_bounds, upper_bounds );

        // Create an optimizer. Pass in our OptimizerSystem
        // and the name of the optimization algorithm.
        Optimizer opt(sys, SimTK::LBFGSB);

        // Specify settings for the optimizer
        opt.setConvergenceTolerance(0.000001);
        opt.useNumericalGradient(true);
        opt.setMaxIterations(1000);
        opt.setLimitedMemoryHistory(500);

        // Optimize it!
        f = opt.optimize(controls); // f=-0.049390301058364026

        cout << "Elapsed time = " << (std::clock()-startTime)/CLOCKS_PER_SEC << "s" << endl;

        cout << "OpenSim example completed successfully.\n";
    }
    catch (const std::exception& ex)
    {
        std::cout << ex.what() << std::endl;
        return 1;
    }

    // End of main() routine.
    return 0;
}
<commit_msg>Initialization order. Unused variable.<commit_after>/* -------------------------------------------------------------------------- *
 *                     OpenSim:  SimpleOptimizationExample.cpp                      *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2012 Stanford University and the Authors                *
 * Author(s): Ayman Habib                                                *
 *                                                                            *
 * 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.                                             *
 * -------------------------------------------------------------------------- */

/*
 * Example of an OpenSim program that tries to find the elbow flexion angle that maximizes
 * the muscle moment arm of BICshort in the Arm26 model.
 */

//==============================================================================
//==============================================================================
#include <OpenSim/OpenSim.h>
#include <ctime>  // clock(), clock_t, CLOCKS_PER_SEC

using namespace OpenSim;
using namespace SimTK;
using namespace std;

// step count for troubleshooting
int stepCount = 0;

double bestSoFar = Infinity;

class ExampleOptimizationSystem : public OptimizerSystem {
   public:

       /* Constructor class. Parameters passed are accessed in the objectiveFunc() class. */
       ExampleOptimizationSystem(int numParameters, State& s, Model& aModel):
             OptimizerSystem(numParameters),
             numKnobs(numParameters),
             si(s),
             osimModel(aModel){}

    int objectiveFunc(  const Vector &newControls, bool new_coefficients, Real& f ) const override {

        // make a copy of out initial states
        State s = si;

        // Update the coordinate value of r_elbow_flex
        OpenSim::Coordinate& elbowFlexCoord = osimModel.updCoordinateSet().get("r_elbow_flex");
        elbowFlexCoord.setValue(s, newControls[0]);
        // Now equilibrate muscles at this configuration
        const Set<Muscle> &muscleSet = osimModel.getMuscles();
        // Make sure other muscle states are initialized the same with 1.0 activation, 0.1 fiberLength followed by equilibrium computation
        for(int i=0; i< muscleSet.getSize(); i++ ){
            muscleSet[i].setActivation(s, 1.0);
            const ActivationFiberLengthMuscle* afl = ActivationFiberLengthMuscle::safeDownCast(&muscleSet[i]);
            if (afl) afl->setFiberLength(s, .1);
        }
        // Make sure the muscles states are in equilibrium
        osimModel.equilibrateMuscles(s);

        const OpenSim::Muscle& bicShort = osimModel.getMuscles().get("BICshort");
        // Compute moment arm of BICshort, flip sign since the optimizer tries to minimize rather than maximize
        f = -bicShort.computeMomentArm(s, elbowFlexCoord);

        stepCount++;

        if( f < bestSoFar){
            bestSoFar = f;
            cout << "\nobjective evaluation #: " << stepCount << " elbow flexion angle = " << newControls[0]*SimTK_RADIAN_TO_DEGREE <<  " BICshort moment arm  = " << -f << std::endl;
        }

      return(0);

   }

private:
    int numKnobs;
    State& si;
    Model& osimModel;
 };

//______________________________________________________________________________
/**
 * Define an optimization problem that finds a set of muscle controls to maximize
 * the forward velocity of the forearm/hand segment mass center.
 */
int main()
{
    try {
        std::clock_t startTime = std::clock();

        // Create a new OpenSim model
        // Similar to arm26 model but without wrapping surfaces for better performance
        Model osimModel("Arm26_Optimize.osim");

        // Initialize the system and get the state representing the state system
        State& si = osimModel.initSystem();

        // initialize the starting shoulder angle
        const CoordinateSet& coords = osimModel.getCoordinateSet();
        coords.get("r_shoulder_elev").setValue(si, 0.0);

        // Set the initial muscle activations
        const Set<Muscle> &muscleSet = osimModel.getMuscles();
        for(int i=0; i< muscleSet.getSize(); i++ ){
            muscleSet[i].setActivation(si, 1.0);
            const ActivationFiberLengthMuscle* afl = ActivationFiberLengthMuscle::safeDownCast(&muscleSet[i]);
            afl->setFiberLength(si, .1);
        }
        OpenSim::Coordinate& elbowFlexCoord = osimModel.updCoordinateSet().get("r_elbow_flex");
        elbowFlexCoord.setValue(si, 1.0);
        //osimModel.getMultibodySystem().realize(si, Stage::Velocity);
        // Make sure the muscles states are in equilibrium
        osimModel.equilibrateMuscles(si);

        // Initialize the optimizer system we've defined.
        ExampleOptimizationSystem sys(1, si, osimModel);
        // Real f = NaN;

        /* Define initial values and bounds for the controls to optimize */

        Vector controls(1, 1.0); // 1 radian for default value
        Vector lower_bounds(1, elbowFlexCoord.getRangeMin());
        Vector upper_bounds(1, elbowFlexCoord.getRangeMax());

        sys.setParameterLimits( lower_bounds, upper_bounds );

        // Create an optimizer. Pass in our OptimizerSystem
        // and the name of the optimization algorithm.
        Optimizer opt(sys, SimTK::LBFGSB);

        // Specify settings for the optimizer
        opt.setConvergenceTolerance(0.000001);
        opt.useNumericalGradient(true);
        opt.setMaxIterations(1000);
        opt.setLimitedMemoryHistory(500);

        // Optimize it!
        /*f = */opt.optimize(controls); // f=-0.049390301058364026

        cout << "Elapsed time = " << (std::clock()-startTime)/CLOCKS_PER_SEC << "s" << endl;

        cout << "OpenSim example completed successfully.\n";
    }
    catch (const std::exception& ex)
    {
        std::cout << ex.what() << std::endl;
        return 1;
    }

    // End of main() routine.
    return 0;
}
<|endoftext|>


<commit_before>/**
 * @file Result.hpp
 * @author Nicolas Di Prima <nicolas@di-prima.fr>
 * @date 2016/05/22
 * @copyright 2016, Nicolas Di Prima. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name of the author nor the names of his contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 AUTHORS 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.
 *
 * @brief define a templated type as place holder for a result of a given
 *        type or an error.
 *
 * The main idea is to provide code and APIs as simple to read and maintain
 * as possible. It is too often difficult to determine what a given function
 * may do, the kind of error it may throw etc...
 *
 * Uses this type to wrap the return values of your function.
 *
 * For example:
 *
 * @code{cpp}
 * // from the following line:
 * int devide_1(int input_1, int input_2, int* output);
 *
 * // to the function
 * Result<int> devide_2(int input_1, int input_2) {
 *   if (!input_2) {
 *     return std::domain_error("division by zero");
 *   }
 *   return input_1 / input_2;
 * }
 * @encode
 *
 * And it is also very simple to use:
 *
 * @code{cpp}
 * // you can simply unwrap it (will throw if error)
 * int res = divide_2(2, 2).unwrap();
 * @encode
 * @code{cpp}
 * // override with you own exception if needed
 * int res = divide_2(2, 0).except(std::logic_error("silly me!"));
 * @encode
 *
 */
#ifndef RESULT_HPP_
# define RESULT_HPP_

# include <exception>
# include <stdexcept>
# include <utility>
# include <type_traits>

# include <boost/variant/variant.hpp>
# include <boost/variant/get.hpp>

/* Helper Macros *********************************************************** */

/// @macro TRY
/// @brief helper to unwrap a Result without throwing an exception (but
///        propagating the error.
///
/// @code{cpp}
/// Result<int> my_func1();
/// Result<int> my_func2() {
///   int i = TRY(my_func1());
///   return i % 2;
/// }
/// @encode
///
/// include this header file with defined **DONT_DEFINE_TRY_MACRO** if you
/// want to define you own one (i.e. add more information along your
/// exception (such as a stack trace?)).
///
# if !defined(DONT_DEFINE_TRY_MACRO)
#  define TRY(expr)           \
    ({                       \
       auto res = expr;      \
       if (res.is_error()) { \
          return res;        \
       }                     \
       res.unwrap();         \
    })
# endif  // ! DONT_DEFINE_TRY_MACRO

/* Result Class ************************************************************ */

/**
 * @class Result
 * @brief placeholder for variant type (result or error)
 */
template<typename R, typename E = std::exception>
class Result {
  static_assert( std::is_base_of<std::exception, E>::value
               , "expecting error type to be base of std::exception"
               );

  static_assert(    std::is_move_constructible<R>::value
                 || std::is_copy_constructible<R>::value
               , "The result type must be move constructible or copy constructible"
               );

 public:
  using return_type = R;
  using error_type  = E;

 public:
  /// @brief Constructors
  /// @{
  Result()                          = delete;
  Result(Result const&)             = delete;
  Result(Result&&)                  = default;

  // non explicit constructor for the return_type
  Result(return_type&&);
  // non explicit constructor for the error_type
  Result(error_type&&);

  /// @brief create a result containing a result object
  ///
  /// This is the only way to create a valid Result.
  ///
  /// @code{cpp}
  /// Result<int> my_func() {
  ///   return Result<int>::Ok(42);
  /// }
  /// @endcode
  static Result<return_type, error_type> Ok(return_type&&) noexcept(false);

  /// @brief create a result containing an error object
  ///
  /// This is the only way to create an error Result
  ///
  /// @code{cpp}
  /// Result<int> my_func() {
  ///   return Result<int>::Err(std::logic_error("no answer"));
  /// }
  /// @encode
  static Result<return_type, error_type> Err(error_type&&) noexcept(false);
  /// @}

  /// @brief Destructor
  /// @{
  ~Result()                        = default;
  /// @}

  /// @brief assignments
  /// @{
  Result& operator=(Result const&) = delete;
  Result& operator=(Result&&)      = default;
  /// @}

  /// @brief const accessors
  ///
  /// these member function does not modify the underlying state
  ///
  /// @{

  /// simple function to check if the given Result contains
  /// a result.
  bool is_ok() const noexcept;

  /// simple function to check if the given Result contains
  /// an error.
  bool is_error() const noexcept;
  /// @}

  /// @brief non-const accessors (will move the content)
  ///
  /// It means: do not reuse the object...
  ///
  /// @{

  /// @brief map the result with the given function
  ///
  /// If the given Result contains a return value (not an error)
  /// then the given function will be called.
  ///
  /// NB: the function validity is not checked.
  ///
  /// @code{cpp}
  /// Result<int> my_func();
  /// struct my_data { int i_; my_data(int i) : i_(i) {} };
  /// my_data c = my_func()
  ///                 .map_res([](int&& i) { return my_data(i); })
  ///                 .unwrap();
  /// @endcode
  template<typename RR, typename F>
  Result<RR, error_type> map_res(F);

  /// @brief map the error of the given result
  ///
  /// you can update the error with more information or change its type
  template<typename EE, typename F>
  Result<return_type, EE> map_err(F);

  /// @brief if the Result is successful, call the next function
  template<typename RR, typename F>
  Result<RR, error_type> and_then(F f) {
    if (this->is_error()) {
      return Result<RR, error_type>::Err(this->get_error());
    }
    return f(this->get_return());
  }
  /// @brief if the Result has error, call the next function
  template<typename RR, typename F>
  Result<RR, error_type> or_else(F f) {
    if (this->is_ok()) {
      return Result<RR, error_type>::Ok(this->get_return());
    }
    return f(this->get_return());
  }

  /// @brief get the result (or throw the underlying error)
  return_type unwrap() noexcept(false);

  /// @brief expected an error (consume the error)
  template<class EE>
  return_type expect(EE const& err) noexcept(false);
  /// @}

 private:

  // private getters
  return_type get_return() const noexcept(false);
  error_type get_error() const noexcept(false);

  // assertions
  void expect_valid_state() const noexcept(false);
  void expect_return() const noexcept(false);
  void expect_error() const noexcept(false);

 private:
  boost::variant<return_type, error_type> internal_;
};

/* ***************************************************************************
 *                                                                           *
 *                            Implementation                                 *
 *                                                                           *
 *************************************************************************** */

/* Public members ********************************************************** */

/* Constructors */

template<typename R, typename E>
Result<R, E> Result<R, E>::Ok(R&& ret) noexcept(false) {
  return Result<R, E>(std::move(ret));
}
template<typename R, typename E>
Result<R, E> Result<R, E>::Err(E&& err) noexcept(false) {
  return Result<R, E>(std::move(err));
}

/* Const accessors */

template<typename R, typename E>
bool Result<R, E>::is_ok() const noexcept { return this->internal_.which() == 0; }
template<typename R, typename E>
bool Result<R, E>::is_error() const noexcept { return this->internal_.which() == 1; }

/* Non-const accessors */

template<typename R, typename E>
template<typename RR, typename F>
Result<RR, E> Result<R, E>::map_res(F f) {
  if (this->is_error()) { return Result<RR, E>::Err(this->get_error()); }
  return Result<RR, E>::Ok(f(this->get_return()));
}

template<typename R, typename E>
template<typename EE, typename F>
Result<R, EE> Result<R, E>::map_err(F f) {
  if (this->is_ok()) { return Result<R, EE>::Ok(this->get_return()); }
  return Result<R, EE>::Err(f(this->get_error()));
}

template<typename R, typename E>
R Result<R, E>::unwrap() noexcept(false) {
  if (this->is_error()) { throw this->get_error(); }
  return this->get_return();
}

template<typename R, typename E>
template<class EE>
R Result<R, E>::expect(EE const& err) noexcept(false) {
  static_assert( std::is_base_of<std::exception, EE>::value
               , "expectation can only fail with std::exception or inherited types"
               );
  this->expect_valid_state();
  if (this->is_error()) { throw err; }
  return this->get_return();
}

/* Private members ********************************************************* */

/* constructors */

template<typename R, typename E>
Result<R, E>::Result(R&& ret) : internal_(std::move(ret)) { }
template<typename R, typename E>
Result<R, E>::Result(E&& err) : internal_(std::move(err)) { }

/* Getters */

template<typename R, typename E>
R Result<R, E>::get_return() const noexcept(false) {
  this->expect_valid_state();
  this->expect_return();
  return boost::get<return_type>(this->internal_);
}
template<typename R, typename E>
E Result<R, E>::get_error() const noexcept(false) {
  this->expect_valid_state();
  this->expect_error();
  return boost::get<error_type>(this->internal_);
}

/* Assertions */

template<typename R, typename E>
void Result<R, E>::expect_valid_state() const noexcept(false) {
  if (this->internal_.empty()) {
    // if this happens, it means the underlying boost variant
    // is empty. This should never happen!
    throw
      std::logic_error("this object is not in a valid state");
  }
}
template<typename R, typename E>
void Result<R, E>::expect_return() const noexcept(false) {
  if (this->is_error()) {
    throw std::logic_error("attempt to read the return of an error");
  }
}
template<typename R, typename E>
void Result<R, E>::expect_error() const noexcept(false) {
  if (this->is_ok()) {
    throw std::logic_error("attempt to read the error of a valid result");
  }
}

#endif /* ! RESULT_HPP_  */

/* vim: set ts=2 sw=2 et:  */
<commit_msg>allow copy constructor of the result type<commit_after>/**
 * @file Result.hpp
 * @author Nicolas Di Prima <nicolas@di-prima.fr>
 * @date 2016/05/22
 * @copyright 2016, Nicolas Di Prima. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name of the author nor the names of his contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 AUTHORS 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.
 *
 * @brief define a templated type as place holder for a result of a given
 *        type or an error.
 *
 * The main idea is to provide code and APIs as simple to read and maintain
 * as possible. It is too often difficult to determine what a given function
 * may do, the kind of error it may throw etc...
 *
 * Uses this type to wrap the return values of your function.
 *
 * For example:
 *
 * @code{cpp}
 * // from the following line:
 * int devide_1(int input_1, int input_2, int* output);
 *
 * // to the function
 * Result<int> devide_2(int input_1, int input_2) {
 *   if (!input_2) {
 *     return std::domain_error("division by zero");
 *   }
 *   return input_1 / input_2;
 * }
 * @encode
 *
 * And it is also very simple to use:
 *
 * @code{cpp}
 * // you can simply unwrap it (will throw if error)
 * int res = divide_2(2, 2).unwrap();
 * @encode
 * @code{cpp}
 * // override with you own exception if needed
 * int res = divide_2(2, 0).except(std::logic_error("silly me!"));
 * @encode
 *
 */
#ifndef RESULT_HPP_
# define RESULT_HPP_

# include <exception>
# include <stdexcept>
# include <utility>
# include <type_traits>

# include <boost/variant/variant.hpp>
# include <boost/variant/get.hpp>

/* Helper Macros *********************************************************** */

/// @macro TRY
/// @brief helper to unwrap a Result without throwing an exception (but
///        propagating the error.
///
/// @code{cpp}
/// Result<int> my_func1();
/// Result<int> my_func2() {
///   int i = TRY(my_func1());
///   return i % 2;
/// }
/// @encode
///
/// include this header file with defined **DONT_DEFINE_TRY_MACRO** if you
/// want to define you own one (i.e. add more information along your
/// exception (such as a stack trace?)).
///
# if !defined(DONT_DEFINE_TRY_MACRO)
#  define TRY(expr)           \
    ({                       \
       auto res = expr;      \
       if (res.is_error()) { \
          return res;        \
       }                     \
       res.unwrap();         \
    })
# endif  // ! DONT_DEFINE_TRY_MACRO

/* Result Class ************************************************************ */

/**
 * @class Result
 * @brief placeholder for variant type (result or error)
 */
template<typename R, typename E = std::exception>
class Result {
  static_assert( std::is_base_of<std::exception, E>::value
               , "expecting error type to be base of std::exception"
               );

  static_assert(    std::is_move_constructible<R>::value
                 || std::is_copy_constructible<R>::value
               , "The result type must be move constructible or copy constructible"
               );

 public:
  using return_type = R;
  using error_type  = E;

 public:
  /// @brief Constructors
  /// @{
  Result()                          = delete;
  Result(Result const&)             = delete;
  Result(Result&&)                  = default;

  // non explicit constructor for the return_type
  Result(return_type&&);
  Result(return_type&);
  // non explicit constructor for the error_type
  Result(error_type&&);

  /// @brief create a result containing a result object
  ///
  /// This is the only way to create a valid Result.
  ///
  /// @code{cpp}
  /// Result<int> my_func() {
  ///   return Result<int>::Ok(42);
  /// }
  /// @endcode
  static Result<return_type, error_type> Ok(return_type&&) noexcept(false);

  /// @brief create a result containing an error object
  ///
  /// This is the only way to create an error Result
  ///
  /// @code{cpp}
  /// Result<int> my_func() {
  ///   return Result<int>::Err(std::logic_error("no answer"));
  /// }
  /// @encode
  static Result<return_type, error_type> Err(error_type&&) noexcept(false);
  /// @}

  /// @brief Destructor
  /// @{
  ~Result()                        = default;
  /// @}

  /// @brief assignments
  /// @{
  Result& operator=(Result const&) = delete;
  Result& operator=(Result&&)      = default;
  /// @}

  /// @brief const accessors
  ///
  /// these member function does not modify the underlying state
  ///
  /// @{

  /// simple function to check if the given Result contains
  /// a result.
  bool is_ok() const noexcept;

  /// simple function to check if the given Result contains
  /// an error.
  bool is_error() const noexcept;
  /// @}

  /// @brief non-const accessors (will move the content)
  ///
  /// It means: do not reuse the object...
  ///
  /// @{

  /// @brief map the result with the given function
  ///
  /// If the given Result contains a return value (not an error)
  /// then the given function will be called.
  ///
  /// NB: the function validity is not checked.
  ///
  /// @code{cpp}
  /// Result<int> my_func();
  /// struct my_data { int i_; my_data(int i) : i_(i) {} };
  /// my_data c = my_func()
  ///                 .map_res([](int&& i) { return my_data(i); })
  ///                 .unwrap();
  /// @endcode
  template<typename RR, typename F>
  Result<RR, error_type> map_res(F);

  /// @brief map the error of the given result
  ///
  /// you can update the error with more information or change its type
  template<typename EE, typename F>
  Result<return_type, EE> map_err(F);

  /// @brief if the Result is successful, call the next function
  template<typename RR, typename F>
  Result<RR, error_type> and_then(F f) {
    if (this->is_error()) {
      return Result<RR, error_type>::Err(this->get_error());
    }
    return f(this->get_return());
  }
  /// @brief if the Result has error, call the next function
  template<typename RR, typename F>
  Result<RR, error_type> or_else(F f) {
    if (this->is_ok()) {
      return Result<RR, error_type>::Ok(this->get_return());
    }
    return f(this->get_return());
  }

  /// @brief get the result (or throw the underlying error)
  return_type unwrap() noexcept(false);

  /// @brief expected an error (consume the error)
  template<class EE>
  return_type expect(EE const& err) noexcept(false);
  /// @}

 private:

  // private getters
  return_type get_return() const noexcept(false);
  error_type get_error() const noexcept(false);

  // assertions
  void expect_valid_state() const noexcept(false);
  void expect_return() const noexcept(false);
  void expect_error() const noexcept(false);

 private:
  boost::variant<return_type, error_type> internal_;
};

/* ***************************************************************************
 *                                                                           *
 *                            Implementation                                 *
 *                                                                           *
 *************************************************************************** */

/* Public members ********************************************************** */

/* Constructors */

template<typename R, typename E>
Result<R, E> Result<R, E>::Ok(R&& ret) noexcept(false) {
  return Result<R, E>(std::move(ret));
}
template<typename R, typename E>
Result<R, E> Result<R, E>::Err(E&& err) noexcept(false) {
  return Result<R, E>(std::move(err));
}

/* Const accessors */

template<typename R, typename E>
bool Result<R, E>::is_ok() const noexcept { return this->internal_.which() == 0; }
template<typename R, typename E>
bool Result<R, E>::is_error() const noexcept { return this->internal_.which() == 1; }

/* Non-const accessors */

template<typename R, typename E>
template<typename RR, typename F>
Result<RR, E> Result<R, E>::map_res(F f) {
  if (this->is_error()) { return Result<RR, E>::Err(this->get_error()); }
  return Result<RR, E>::Ok(f(this->get_return()));
}

template<typename R, typename E>
template<typename EE, typename F>
Result<R, EE> Result<R, E>::map_err(F f) {
  if (this->is_ok()) { return Result<R, EE>::Ok(this->get_return()); }
  return Result<R, EE>::Err(f(this->get_error()));
}

template<typename R, typename E>
R Result<R, E>::unwrap() noexcept(false) {
  if (this->is_error()) { throw this->get_error(); }
  return this->get_return();
}

template<typename R, typename E>
template<class EE>
R Result<R, E>::expect(EE const& err) noexcept(false) {
  static_assert( std::is_base_of<std::exception, EE>::value
               , "expectation can only fail with std::exception or inherited types"
               );
  this->expect_valid_state();
  if (this->is_error()) { throw err; }
  return this->get_return();
}

/* Private members ********************************************************* */

/* constructors */

template<typename R, typename E>
Result<R, E>::Result(R&& ret) : internal_(std::move(ret)) { }
template<typename R, typename E>
Result<R, E>::Result(R& ret)  : internal_(ret) { }
template<typename R, typename E>
Result<R, E>::Result(E&& err) : internal_(std::move(err)) { }

/* Getters */

template<typename R, typename E>
R Result<R, E>::get_return() const noexcept(false) {
  this->expect_valid_state();
  this->expect_return();
  return boost::get<return_type>(this->internal_);
}
template<typename R, typename E>
E Result<R, E>::get_error() const noexcept(false) {
  this->expect_valid_state();
  this->expect_error();
  return boost::get<error_type>(this->internal_);
}

/* Assertions */

template<typename R, typename E>
void Result<R, E>::expect_valid_state() const noexcept(false) {
  if (this->internal_.empty()) {
    // if this happens, it means the underlying boost variant
    // is empty. This should never happen!
    throw
      std::logic_error("this object is not in a valid state");
  }
}
template<typename R, typename E>
void Result<R, E>::expect_return() const noexcept(false) {
  if (this->is_error()) {
    throw std::logic_error("attempt to read the return of an error");
  }
}
template<typename R, typename E>
void Result<R, E>::expect_error() const noexcept(false) {
  if (this->is_ok()) {
    throw std::logic_error("attempt to read the error of a valid result");
  }
}

#endif /* ! RESULT_HPP_  */

/* vim: set ts=2 sw=2 et:  */
<|endoftext|>


<commit_before>/* Copyright (C) 2005, Thorvald Natvig <thorvald@natvig.com>

   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 Mumble Developers 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 FOUNDATION 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 "Server.h"

Server *g_sServer;

Server::Server() {
	m_qtsServer = new QTcpServer(this);

	connect(m_qtsServer, SIGNAL(newConnection()), this, SLOT(newClient()));

	if (! m_qtsServer->listen(QHostAddress::Any, 64738))
		qFatal("Server: Listen failed");
}

void Server::newClient() {
	Connection *cCon = new Connection(this, m_qtsServer->nextPendingConnection());

	short id;

	for(id=1;id<32000;id++)
		if (! g_sServer->m_qmConnections.contains(id))
			break;

	Player *pPlayer = Player::add(id);
	m_qmPlayers[cCon] = pPlayer;

	connect(cCon, SIGNAL(connectionClosed(Connection *)), this, SLOT(connectionClosed(Connection *)));
	connect(cCon, SIGNAL(message(QByteArray &, Connection *)), this, SLOT(message(QByteArray &, Connection *)));
}

void Server::connectionClosed(Connection *c) {
	Player *pPlayer = m_qmPlayers.value(c);

	if (pPlayer->m_sState == Player::Authenticated) {
		MessageServerLeave mslMsg;
		mslMsg.m_sPlayerId=pPlayer->m_sId;
		sendExcept(&mslMsg, c);
	}

	m_qmConnections.remove(pPlayer->m_sId);
	m_qmPlayers.remove(c);

	qWarning("Connection closed");

	Player::remove(pPlayer);

	delete pPlayer;
	c->deleteLater();
}

void Server::message(QByteArray &qbaMsg, Connection *cCon) {
	  Message *mMsg = Message::networkToMessage(qbaMsg);
	  if (mMsg) {
		mMsg->process(cCon);
	  } else {
		cCon->disconnect();
	  }
}

void Server::sendAll(Message *mMsg) {
	sendExcept(mMsg, NULL);
}

void Server::sendExcept(Message *mMsg, Connection *cCon) {
	QMapIterator<Connection *, Player *> iPlayers(m_qmPlayers);
	while (iPlayers.hasNext()) {
		iPlayers.next();
		if (iPlayers.key() != cCon)
			iPlayers.key()->sendMessage(mMsg);
	}
}

#define MSG_SETUP(st) \
  Player *pSrcPlayer = g_sServer->m_qmPlayers[cCon]; \
  Player *pDstPlayer = Player::get(m_sPlayerId); \
  if (pSrcPlayer->m_sState != st) \
  	return

void MessageServerJoin::process(Connection *cCon) {
	MSG_SETUP(Player::Connected);

	pSrcPlayer->m_qsName = m_qsPlayerName;
	m_sPlayerId = pSrcPlayer->m_sId;
	g_sServer->m_qmConnections[pSrcPlayer->m_sId] = cCon;

	g_sServer->sendExcept(this, cCon);

	pSrcPlayer->m_sState = Player::Authenticated;

	qWarning("Player %d:%s joined", pSrcPlayer->m_sId, m_qsPlayerName.toLatin1().constData());

	MessageServerJoin msjMsg;

	QMapIterator<Connection *, Player *> iPlayers(g_sServer->m_qmPlayers);
	while (iPlayers.hasNext()) {
		iPlayers.next();
		Player *pPlayer = iPlayers.value();
		msjMsg.m_sPlayerId = pPlayer->m_sId;
		msjMsg.m_qsPlayerName = pPlayer->m_qsName;
		cCon->sendMessage(&msjMsg);
		qWarning("Notifying of %s", pPlayer->m_qsName.toLatin1().constData());

		if (pPlayer->m_bMute) {
			MessagePlayerMute mpmMsg;
			mpmMsg.m_sPlayerId = pPlayer->m_sId;
			mpmMsg.m_bMute = pPlayer->m_bMute;
			cCon->sendMessage(&mpmMsg);
			qWarning("which is mute");
		}
		if (pPlayer->m_bDeaf) {
			MessagePlayerDeaf mpdMsg;
			mpdMsg.m_sPlayerId = pPlayer->m_sId;
			mpdMsg.m_bDeaf = pPlayer->m_bDeaf;
			cCon->sendMessage(&mpdMsg);
			qWarning("which is deaf");
		}
	}
}

void MessageServerLeave::process(Connection *) {
}

void MessageSpeex::process(Connection *cCon) {
	MSG_SETUP(Player::Authenticated);

	m_sPlayerId = pSrcPlayer->m_sId;

	if (pSrcPlayer->m_bMute)
		return;

	QMapIterator<Connection *, Player *> iPlayers(g_sServer->m_qmPlayers);
	while (iPlayers.hasNext()) {
		iPlayers.next();
		Player *pPlayer = iPlayers.value();
		if (! pPlayer->m_bDeaf && pPlayer != pSrcPlayer)
			iPlayers.key()->sendMessage(this);
	}
}

void MessagePlayerMute::process(Connection *cCon) {
	MSG_SETUP(Player::Authenticated);

	pDstPlayer->m_bMute = m_bMute;

	g_sServer->sendAll(this);
}

void MessagePlayerDeaf::process(Connection *cCon) {
	MSG_SETUP(Player::Authenticated);

	pDstPlayer->m_bDeaf = m_bDeaf;

	g_sServer->sendAll(this);
}

void MessagePlayerKick::process(Connection *cCon) {
	MSG_SETUP(Player::Authenticated);

	cCon = g_sServer->m_qmConnections[m_sPlayerId];
	cCon->sendMessage(this);
	cCon->disconnect();
}
<commit_msg>remove debug output<commit_after>/* Copyright (C) 2005, Thorvald Natvig <thorvald@natvig.com>

   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 Mumble Developers 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 FOUNDATION 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 "Server.h"

Server *g_sServer;

Server::Server() {
	m_qtsServer = new QTcpServer(this);

	connect(m_qtsServer, SIGNAL(newConnection()), this, SLOT(newClient()));

	if (! m_qtsServer->listen(QHostAddress::Any, 64738))
		qFatal("Server: Listen failed");
}

void Server::newClient() {
	Connection *cCon = new Connection(this, m_qtsServer->nextPendingConnection());

	short id;

	for(id=1;id<32000;id++)
		if (! g_sServer->m_qmConnections.contains(id))
			break;

	Player *pPlayer = Player::add(id);
	m_qmPlayers[cCon] = pPlayer;

	connect(cCon, SIGNAL(connectionClosed(Connection *)), this, SLOT(connectionClosed(Connection *)));
	connect(cCon, SIGNAL(message(QByteArray &, Connection *)), this, SLOT(message(QByteArray &, Connection *)));
}

void Server::connectionClosed(Connection *c) {
	Player *pPlayer = m_qmPlayers.value(c);

	if (pPlayer->m_sState == Player::Authenticated) {
		MessageServerLeave mslMsg;
		mslMsg.m_sPlayerId=pPlayer->m_sId;
		sendExcept(&mslMsg, c);
	}

	m_qmConnections.remove(pPlayer->m_sId);
	m_qmPlayers.remove(c);

	qWarning("Connection closed");

	Player::remove(pPlayer);

	delete pPlayer;
	c->deleteLater();
}

void Server::message(QByteArray &qbaMsg, Connection *cCon) {
	  Message *mMsg = Message::networkToMessage(qbaMsg);
	  if (mMsg) {
		mMsg->process(cCon);
	  } else {
		cCon->disconnect();
	  }
}

void Server::sendAll(Message *mMsg) {
	sendExcept(mMsg, NULL);
}

void Server::sendExcept(Message *mMsg, Connection *cCon) {
	QMapIterator<Connection *, Player *> iPlayers(m_qmPlayers);
	while (iPlayers.hasNext()) {
		iPlayers.next();
		if (iPlayers.key() != cCon)
			iPlayers.key()->sendMessage(mMsg);
	}
}

#define MSG_SETUP(st) \
  Player *pSrcPlayer = g_sServer->m_qmPlayers[cCon]; \
  Player *pDstPlayer = Player::get(m_sPlayerId); \
  if (pSrcPlayer->m_sState != st) \
  	return

void MessageServerJoin::process(Connection *cCon) {
	MSG_SETUP(Player::Connected);

	pSrcPlayer->m_qsName = m_qsPlayerName;
	m_sPlayerId = pSrcPlayer->m_sId;
	g_sServer->m_qmConnections[pSrcPlayer->m_sId] = cCon;

	g_sServer->sendExcept(this, cCon);

	pSrcPlayer->m_sState = Player::Authenticated;

	qWarning("Player %d:%s joined", pSrcPlayer->m_sId, m_qsPlayerName.toLatin1().constData());

	MessageServerJoin msjMsg;

	QMapIterator<Connection *, Player *> iPlayers(g_sServer->m_qmPlayers);
	while (iPlayers.hasNext()) {
		iPlayers.next();
		Player *pPlayer = iPlayers.value();
		msjMsg.m_sPlayerId = pPlayer->m_sId;
		msjMsg.m_qsPlayerName = pPlayer->m_qsName;
		cCon->sendMessage(&msjMsg);

		if (pPlayer->m_bMute) {
			MessagePlayerMute mpmMsg;
			mpmMsg.m_sPlayerId = pPlayer->m_sId;
			mpmMsg.m_bMute = pPlayer->m_bMute;
			cCon->sendMessage(&mpmMsg);
		}
		if (pPlayer->m_bDeaf) {
			MessagePlayerDeaf mpdMsg;
			mpdMsg.m_sPlayerId = pPlayer->m_sId;
			mpdMsg.m_bDeaf = pPlayer->m_bDeaf;
			cCon->sendMessage(&mpdMsg);
		}
	}
}

void MessageServerLeave::process(Connection *) {
}

void MessageSpeex::process(Connection *cCon) {
	MSG_SETUP(Player::Authenticated);

	m_sPlayerId = pSrcPlayer->m_sId;

	if (pSrcPlayer->m_bMute)
		return;

	QMapIterator<Connection *, Player *> iPlayers(g_sServer->m_qmPlayers);
	while (iPlayers.hasNext()) {
		iPlayers.next();
		Player *pPlayer = iPlayers.value();
		if (! pPlayer->m_bDeaf && pPlayer != pSrcPlayer)
			iPlayers.key()->sendMessage(this);
	}
}

void MessagePlayerMute::process(Connection *cCon) {
	MSG_SETUP(Player::Authenticated);

	pDstPlayer->m_bMute = m_bMute;

	g_sServer->sendAll(this);
}

void MessagePlayerDeaf::process(Connection *cCon) {
	MSG_SETUP(Player::Authenticated);

	pDstPlayer->m_bDeaf = m_bDeaf;

	g_sServer->sendAll(this);
}

void MessagePlayerKick::process(Connection *cCon) {
	MSG_SETUP(Player::Authenticated);

	cCon = g_sServer->m_qmConnections[m_sPlayerId];
	cCon->sendMessage(this);
	cCon->disconnect();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: MDatabaseMetaDataHelper.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2004-03-17 10:42:12 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _CONNECTIVITY_MAB_DATABASEMETADATAHELPER_HXX_
#define _CONNECTIVITY_MAB_DATABASEMETADATAHELPER_HXX_

 /*
#ifndef _COM_SUN_STAR_SDBC_XRESULTSET_HPP_
#include <com/sun/star/sdbc/XResultSet.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_
#include <com/sun/star/sdbc/XRow.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_
#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XCLOSEABLE_HPP_
#include <com/sun/star/sdbc/XCloseable.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XCOLUMNLOCATE_HPP_
#include <com/sun/star/sdbc/XColumnLocate.hpp>
#endif
#ifndef _COM_SUN_STAR_UTIL_XCANCELLABLE_HPP_
#include <com/sun/star/util/XCancellable.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XWARNINGSSUPPLIER_HPP_
#include <com/sun/star/sdbc/XWarningsSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XRESULTSETUPDATE_HPP_
#include <com/sun/star/sdbc/XResultSetUpdate.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XROWUPDATE_HPP_
#include <com/sun/star/sdbc/XRowUpdate.hpp>
#endif
#ifndef _CPPUHELPER_COMPBASE7_HXX_
#include <cppuhelper/compbase7.hxx>
#endif
*/
#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_
#include <comphelper/proparrhlp.hxx>
#endif
 /*
#ifndef _CONNECTIVITY_FILE_ASTATEMENT_HXX_
#include "file/FStatement.hxx"
#endif
#ifndef _CONNECTIVITY_COMMONTOOLS_HXX_
#include "connectivity/CommonTools.hxx"
#endif
*/
#ifndef _COMPHELPER_PROPERTYCONTAINER_HXX_
#include <comphelper/propertycontainer.hxx>
#endif

#ifndef _CONNECTIVITY_FDATABASEMETADATARESULTSET_HXX_
#include "FDatabaseMetaDataResultSet.hxx"
#endif

#ifndef _CONNECTIVITY_MAB_CONNECTION_HXX_
#include <MConnection.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif

namespace connectivity
{
    namespace mozab
    {
        class MDatabaseMetaDataHelper
        {
        public:
            MDatabaseMetaDataHelper( );
            ~MDatabaseMetaDataHelper();

            sal_Bool getTableStrings( OConnection*                        _pCon,
                                      ::std::vector< ::rtl::OUString >&   _rStrings,
                                      ::std::vector< ::rtl::OUString >&   _rTypes,
                                      sal_Bool                            forceLoad = sal_False );

            sal_Bool getTables( OConnection* _pCon,
                                const ::rtl::OUString& tableNamePattern,
                                const ::com::sun::star::uno::Sequence< ::rtl::OUString >& types,
                                ODatabaseMetaDataResultSet::ORows& _rRows);

            const ::rtl::OUString& getErrorString() { return m_aErrorString; }

            sal_Bool    testLDAPConnection( OConnection* _pCon );

        private:
            sal_Bool                            m_bProfileExists ;
            ::std::vector< ::rtl::OUString >    m_aTableNames;
            ::std::vector< ::rtl::OUString >    m_aTableTypes;
            ::rtl::OUString                     m_aErrorString;

            void setAbSpecificError( OConnection* _pCon, sal_Bool bGivenURI );
        };
    }

}
#endif // _CONNECTIVITY_MAB_DATABASEMETADATAHELPER_HXX_

<commit_msg>INTEGRATION: CWS mozab04 (1.4.2); FILE MERGED 2004/04/12 10:15:54 windly 1.4.2.1: #i6883# make mozab driver threadsafe<commit_after>/*************************************************************************
 *
 *  $RCSfile: MDatabaseMetaDataHelper.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hjs $ $Date: 2004-06-25 18:31:40 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _CONNECTIVITY_MAB_DATABASEMETADATAHELPER_HXX_
#define _CONNECTIVITY_MAB_DATABASEMETADATAHELPER_HXX_

 /*
#ifndef _COM_SUN_STAR_SDBC_XRESULTSET_HPP_
#include <com/sun/star/sdbc/XResultSet.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_
#include <com/sun/star/sdbc/XRow.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_
#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XCLOSEABLE_HPP_
#include <com/sun/star/sdbc/XCloseable.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XCOLUMNLOCATE_HPP_
#include <com/sun/star/sdbc/XColumnLocate.hpp>
#endif
#ifndef _COM_SUN_STAR_UTIL_XCANCELLABLE_HPP_
#include <com/sun/star/util/XCancellable.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XWARNINGSSUPPLIER_HPP_
#include <com/sun/star/sdbc/XWarningsSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XRESULTSETUPDATE_HPP_
#include <com/sun/star/sdbc/XResultSetUpdate.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XROWUPDATE_HPP_
#include <com/sun/star/sdbc/XRowUpdate.hpp>
#endif
#ifndef _CPPUHELPER_COMPBASE7_HXX_
#include <cppuhelper/compbase7.hxx>
#endif
*/
#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_
#include <comphelper/proparrhlp.hxx>
#endif
 /*
#ifndef _CONNECTIVITY_FILE_ASTATEMENT_HXX_
#include "file/FStatement.hxx"
#endif
#ifndef _CONNECTIVITY_COMMONTOOLS_HXX_
#include "connectivity/CommonTools.hxx"
#endif
*/
#ifndef _COMPHELPER_PROPERTYCONTAINER_HXX_
#include <comphelper/propertycontainer.hxx>
#endif

#ifndef _CONNECTIVITY_FDATABASEMETADATARESULTSET_HXX_
#include "FDatabaseMetaDataResultSet.hxx"
#endif

#ifndef _CONNECTIVITY_MAB_CONNECTION_HXX_
#include <MConnection.hxx>
#endif
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif

namespace connectivity
{
    namespace mozab
    {
        class MDatabaseMetaDataHelper
        {
        public:
            MDatabaseMetaDataHelper( );
            ~MDatabaseMetaDataHelper();

            //PROXIED_FUNCTION
            sal_Bool getTableStrings( OConnection*                        _pCon,
                                      ::std::vector< ::rtl::OUString >&   _rStrings,
                                      ::std::vector< ::rtl::OUString >&   _rTypes);

            sal_Bool getTables( OConnection* _pCon,
                                const ::rtl::OUString& tableNamePattern,
                                const ::com::sun::star::uno::Sequence< ::rtl::OUString >& types,
                                ODatabaseMetaDataResultSet::ORows& _rRows);

            const ::rtl::OUString& getErrorString() { return m_aErrorString; }

            sal_Bool   testLDAPConnection( OConnection* _pCon );
            sal_Bool   NewAddressBook( OConnection* _pCon,const ::rtl::OUString & aTableName);

        private:
            sal_Bool                            m_bProfileExists ;
            ::std::vector< ::rtl::OUString >    m_aTableNames;
            ::std::vector< ::rtl::OUString >    m_aTableTypes;
            ::rtl::OUString                     m_aErrorString;
            void setAbSpecificError( OConnection* _pCon, sal_Bool bGivenURI );
        };
    }

}
#endif // _CONNECTIVITY_MAB_DATABASEMETADATAHELPER_HXX_

<|endoftext|>


<commit_before>// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <regex>

// template <class charT> struct regex_traits;

// charT translate_nocase(charT c) const;

// REQUIRES: locale.en_US.UTF-8

// XFAIL: with_system_cxx_lib=macosx10.7
// XFAIL: with_system_cxx_lib=macosx10.8

// TODO: investigation needed
// XFAIL: linux-gnu

#include <regex>
#include <cassert>

#include "test_macros.h"
#include "platform_support.h"

int main()
{
    {
        std::regex_traits<char> t;
        assert(t.translate_nocase(' ') == ' ');
        assert(t.translate_nocase('A') == 'a');
        assert(t.translate_nocase('\x07') == '\x07');
        assert(t.translate_nocase('.') == '.');
        assert(t.translate_nocase('a') == 'a');
        assert(t.translate_nocase('1') == '1');
        assert(t.translate_nocase('\xDA') == '\xDA');
        assert(t.translate_nocase('\xFA') == '\xFA');
        t.imbue(std::locale(LOCALE_en_US_UTF_8));
        assert(t.translate_nocase(' ') == ' ');
        assert(t.translate_nocase('A') == 'a');
        assert(t.translate_nocase('\x07') == '\x07');
        assert(t.translate_nocase('.') == '.');
        assert(t.translate_nocase('a') == 'a');
        assert(t.translate_nocase('1') == '1');
        assert(t.translate_nocase('\xDA') == '\xFA');
        assert(t.translate_nocase('\xFA') == '\xFA');
    }
    {
        std::regex_traits<wchar_t> t;
        assert(t.translate_nocase(L' ') == L' ');
        assert(t.translate_nocase(L'A') == L'a');
        assert(t.translate_nocase(L'\x07') == L'\x07');
        assert(t.translate_nocase(L'.') == L'.');
        assert(t.translate_nocase(L'a') == L'a');
        assert(t.translate_nocase(L'1') == L'1');
        assert(t.translate_nocase(L'\xDA') == L'\xDA');
        assert(t.translate_nocase(L'\xFA') == L'\xFA');
        t.imbue(std::locale(LOCALE_en_US_UTF_8));
        assert(t.translate_nocase(L' ') == L' ');
        assert(t.translate_nocase(L'A') == L'a');
        assert(t.translate_nocase(L'\x07') == L'\x07');
        assert(t.translate_nocase(L'.') == L'.');
        assert(t.translate_nocase(L'a') == L'a');
        assert(t.translate_nocase(L'1') == L'1');
        assert(t.translate_nocase(L'\xDA') == L'\xFA');
        assert(t.translate_nocase(L'\xFA') == L'\xFA');
    }
}
<commit_msg>[test] [re.traits] Remove asserts failing due to invalid UTF-8<commit_after>// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <regex>

// template <class charT> struct regex_traits;

// charT translate_nocase(charT c) const;

// REQUIRES: locale.en_US.UTF-8

// XFAIL: with_system_cxx_lib=macosx10.7
// XFAIL: with_system_cxx_lib=macosx10.8

#include <regex>
#include <cassert>

#include "test_macros.h"
#include "platform_support.h"

int main()
{
    {
        std::regex_traits<char> t;
        assert(t.translate_nocase(' ') == ' ');
        assert(t.translate_nocase('A') == 'a');
        assert(t.translate_nocase('\x07') == '\x07');
        assert(t.translate_nocase('.') == '.');
        assert(t.translate_nocase('a') == 'a');
        assert(t.translate_nocase('1') == '1');
        assert(t.translate_nocase('\xDA') == '\xDA');
        assert(t.translate_nocase('\xFA') == '\xFA');
        t.imbue(std::locale(LOCALE_en_US_UTF_8));
        assert(t.translate_nocase(' ') == ' ');
        assert(t.translate_nocase('A') == 'a');
        assert(t.translate_nocase('\x07') == '\x07');
        assert(t.translate_nocase('.') == '.');
        assert(t.translate_nocase('a') == 'a');
        assert(t.translate_nocase('1') == '1');
    }
    {
        std::regex_traits<wchar_t> t;
        assert(t.translate_nocase(L' ') == L' ');
        assert(t.translate_nocase(L'A') == L'a');
        assert(t.translate_nocase(L'\x07') == L'\x07');
        assert(t.translate_nocase(L'.') == L'.');
        assert(t.translate_nocase(L'a') == L'a');
        assert(t.translate_nocase(L'1') == L'1');
        assert(t.translate_nocase(L'\xDA') == L'\xDA');
        assert(t.translate_nocase(L'\xFA') == L'\xFA');
        t.imbue(std::locale(LOCALE_en_US_UTF_8));
        assert(t.translate_nocase(L' ') == L' ');
        assert(t.translate_nocase(L'A') == L'a');
        assert(t.translate_nocase(L'\x07') == L'\x07');
        assert(t.translate_nocase(L'.') == L'.');
        assert(t.translate_nocase(L'a') == L'a');
        assert(t.translate_nocase(L'1') == L'1');
        assert(t.translate_nocase(L'\xDA') == L'\xFA');
        assert(t.translate_nocase(L'\xFA') == L'\xFA');
    }
}
<|endoftext|>


<commit_before><commit_msg>Parse delegate options in a separate function<commit_after><|endoftext|>


<commit_before>/*
 * Funambol is a mobile platform developed by Funambol, Inc.
 * Copyright (C) 2003 - 2007 Funambol, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
 * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
 *
 * 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 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 or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 *
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */

#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/extensions/HelperMacros.h>

#include "base/fscapi.h"
#include "base/Log.h"
#include "base/util/StringBuffer.h"
#include "base/globalsdef.h"

#include "spds/SyncManagerConfig.h"
#include "spds/SyncReport.h"
#include "spds/SyncManager.h"
#include "spds/spdsutils.h"
#include "spds/SyncMLBuilder.h"

USE_NAMESPACE

#define TEST_SERVER_URL   "http://my.funambol/sync"

#ifdef _WIN32
# define TESTDIR "."
#else
# define TESTDIR "testcases"
#endif

class ServerDevInfTest : public CppUnit::TestFixture {

    CPPUNIT_TEST_SUITE(ServerDevInfTest);

        CPPUNIT_TEST(testAskServerDevInf);
        CPPUNIT_TEST(testPrepareServerDevInf);
        CPPUNIT_TEST(testFormatServerDevInf);
        CPPUNIT_TEST(testProcessServerDevInf1);
        CPPUNIT_TEST(testProcessServerDevInf2);

    CPPUNIT_TEST_SUITE_END();

public:
    void setUp() {

        report.setSyncSourceReports(config);

    }

    void tearDown() {

    }

private:

    SyncManagerConfig config;
    SyncReport report;

    //
    // Test: syncManager::askServerDevInf()
    // ------------------------------------
    void testAskServerDevInf() {

        bool ret = false;
        SyncManager syncManager(config, report);

        // Server url unchanged for tests 1. 2. 3.
        config.setSyncURL          (TEST_SERVER_URL);
        config.setServerLastSyncURL(TEST_SERVER_URL);

        // 1. No Server swv available in config: expect true
        config.setForceServerDevInfo(false);
        config.setServerSwv("");
        ret = syncManager.askServerDevInf();
        CPPUNIT_ASSERT(ret);

        // 2. Server swv available in config: expect false
        config.setForceServerDevInfo(false);
        config.setServerSwv("8.0.0");
        ret = syncManager.askServerDevInf();
        CPPUNIT_ASSERT(!ret);

        // 3. Force it via the config flag: expect true
        config.setForceServerDevInfo(true);
        config.setServerSwv("8.0.0");
        ret = syncManager.askServerDevInf();
        CPPUNIT_ASSERT(ret);

        // 4. Change the server URL: expect true
        config.setForceServerDevInfo(false);
        config.setServerSwv("8.0.0");
        StringBuffer urlModified = config.getSyncURL();
        urlModified.append("_mod");
        config.setServerLastSyncURL(urlModified.c_str());
        ret = syncManager.askServerDevInf();
        CPPUNIT_ASSERT(ret);
    }

    //
    // Test: syncMLBuilder::prepareServerDevInf()
    // ------------------------------------------
    void testPrepareServerDevInf() {

        SyncMLBuilder syncMLBuilder;
        AbstractCommand* command = syncMLBuilder.prepareServerDevInf();
        CPPUNIT_ASSERT(command);

        // Check it's a Get
        StringBuffer name = command->getName();
        CPPUNIT_ASSERT(name == GET);
        Get* get = (Get*)command;
        CPPUNIT_ASSERT(get);

        // Check the meta type = "application/vnd.syncml-devinf+xml"
        Meta* meta = get->getMeta();
        CPPUNIT_ASSERT(meta);
        StringBuffer type = meta->getType();
        CPPUNIT_ASSERT(type == DEVINF_FORMAT);

        ArrayList* items = get->getItems();
        CPPUNIT_ASSERT(items);

        // Expect only 1 item
        CPPUNIT_ASSERT_EQUAL(1, items->size());
        Item* item = (Item*)items->get(0);
        CPPUNIT_ASSERT(item);

        // Check the target locURI = "./devinf12"
        Target* target = item->getTarget();
        CPPUNIT_ASSERT(target);

        StringBuffer locURI = target->getLocURI();
        CPPUNIT_ASSERT(locURI == DEVINF_URI);

        delete command;
    }

    //
    // Test: format the Get command to obtain the Server capabilities
    // --------------------------------------------------------------
    void testFormatServerDevInf() {

        SyncMLBuilder syncMLBuilder;
        ArrayList commands;
        AbstractCommand* get = syncMLBuilder.prepareServerDevInf();
        CPPUNIT_ASSERT(get);

        commands.add(*get);
        delete get;
        SyncML* syncml = syncMLBuilder.prepareInitObject(NULL, NULL, &commands);
        CPPUNIT_ASSERT(syncml);

        char* msg = syncMLBuilder.prepareMsg(syncml);
        CPPUNIT_ASSERT(msg);

        // Check if this part of XML is included in the SyncML msg
        int cmdID = 1;
        StringBuffer expected;
        expected.sprintf("<Get><CmdID>%d</CmdID><Meta><Type xmlns=\"syncml:metinf\">%s</Type></Meta><Item><Target><LocURI>%s</LocURI></Target></Item></Get>",
                         cmdID, DEVINF_FORMAT, DEVINF_URI);

        StringBuffer syncmlMsg(msg);
        syncmlMsg.replaceAll("\n","");
        size_t pos = syncmlMsg.find(expected);
        CPPUNIT_ASSERT(pos != StringBuffer::npos);

        delete [] msg;
        deleteSyncML(&syncml);
    }

    //
    // Test: syncMLProcessor::processServerDevInf()
    // This is a sample XML with devInf Results from Funambol Server
    // -------------------------------------------------------------
    void testProcessServerDevInf1() {

        // Load and parse the sample XML with <Results> command from Server
        config.setSyncURL(TEST_SERVER_URL);
        processDevInf("devInfResults.xml");

        // Check the config has been filled as expected
        StringBuffer url1 = config.getSyncURL();
        StringBuffer url2 = config.getServerLastSyncURL();
        CPPUNIT_ASSERT(url1 == url2);

        int  iVal;
        bool bVal;
        StringBuffer value;
        value = config.getServerSwv();           CPPUNIT_ASSERT(value == "7.1.1");
        value = config.getServerFwv();           CPPUNIT_ASSERT(value == "-");
        value = config.getServerHwv();           CPPUNIT_ASSERT(value == "-");
        value = config.getServerMan();           CPPUNIT_ASSERT(value == "Funambol");
        value = config.getServerMod();           CPPUNIT_ASSERT(value == "DS Server ComEd");
        value = config.getServerOem();           CPPUNIT_ASSERT(value == "-");
        value = config.getServerDevID();         CPPUNIT_ASSERT(value == "funambol");
        value = config.getServerDevType();       CPPUNIT_ASSERT(value == "server");
        value = config.getServerVerDTD();        CPPUNIT_ASSERT(value == "1.2");
        bVal  = config.getServerUtc();           CPPUNIT_ASSERT(bVal  == true);
        bVal  = config.getServerLoSupport();     CPPUNIT_ASSERT(bVal  == true);
        bVal  = config.getServerNocSupport();    CPPUNIT_ASSERT(bVal  == true);
        iVal  = config.getServerSmartSlowSync(); CPPUNIT_ASSERT(iVal  == 1);

    }

    //
    // Test: syncMLProcessor::processServerDevInf()
    // This is a sample XML with devInf Results from OMA specs
    // -------------------------------------------------------
    void testProcessServerDevInf2() {

        // Load and parse the sample XML with <Results> command from Server
        config.setSyncURL(TEST_SERVER_URL);
        processDevInf("devInfResults2.xml");

        // Check the config has been filled as expected
        StringBuffer url1 = config.getSyncURL();
        StringBuffer url2 = config.getServerLastSyncURL();
        CPPUNIT_ASSERT(url1 == url2);

        int  iVal;
        bool bVal;
        StringBuffer value;
        value = config.getServerSwv();           CPPUNIT_ASSERT(value == "1.0.0");
        value = config.getServerFwv();           CPPUNIT_ASSERT(value == "1.0.1");
        value = config.getServerHwv();           CPPUNIT_ASSERT(value == "1.0.2");
        value = config.getServerMan();           CPPUNIT_ASSERT(value == "Small Factory, Ltd.");
        value = config.getServerMod();           CPPUNIT_ASSERT(value == "Tiny Server");
        value = config.getServerOem();           CPPUNIT_ASSERT(value == "Tiny Shop");
        value = config.getServerDevID();         CPPUNIT_ASSERT(value == "485749KR");
        value = config.getServerDevType();       CPPUNIT_ASSERT(value == "Server");
        value = config.getServerVerDTD();        CPPUNIT_ASSERT(value == "1.2");
        bVal  = config.getServerUtc();           CPPUNIT_ASSERT(bVal  == true);
        bVal  = config.getServerLoSupport();     CPPUNIT_ASSERT(bVal  == true);
        bVal  = config.getServerNocSupport();    CPPUNIT_ASSERT(bVal  == true);
        iVal  = config.getServerSmartSlowSync(); CPPUNIT_ASSERT(iVal  == 2);
    }

    /**
     * Utility: will process Server devInf from file 'filename',
     * store data in the config
     */
    void processDevInf(const StringBuffer& filename) {

        StringBuffer xml;
        loadTestFile(filename.c_str(), xml);

        ArrayList commands;
        Parser::getCommands(commands, xml);
        CPPUNIT_ASSERT_MESSAGE("Failed to parse devInf Results", (commands.size() == 1) );

        // Process the Server devInf
        SyncMLProcessor syncMLProcessor;
        AbstractCommand* cmd = (AbstractCommand*)commands.get(0);
        bool found = syncMLProcessor.processServerDevInf(cmd, config);
        CPPUNIT_ASSERT(found);
    }

    /**
     * Load a SyncML message from file, parse and reformat it
     * and return the original message and the converted one.
     */
    void loadTestFile(const char* fileName, StringBuffer& ret) {
        char*       message;
        size_t      len;

        StringBuffer path;
        path.sprintf("%s/%s", TESTDIR, fileName);

        bool fileLoaded = readFile(path, &message, &len, false);
        CPPUNIT_ASSERT_MESSAGE("Failed to load XML", fileLoaded);

        ret = message;
        delete [] message;
    }

};

CPPUNIT_TEST_SUITE_REGISTRATION( ServerDevInfTest );
<commit_msg>fixed ServerDevInfTest: if XSmartSlowSync not defined by Server, its value is 0 (smartslow not supported)<commit_after>/*
 * Funambol is a mobile platform developed by Funambol, Inc.
 * Copyright (C) 2003 - 2007 Funambol, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
 * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
 *
 * 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 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 or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 *
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */

#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/extensions/HelperMacros.h>

#include "base/fscapi.h"
#include "base/Log.h"
#include "base/util/StringBuffer.h"
#include "base/globalsdef.h"

#include "spds/SyncManagerConfig.h"
#include "spds/SyncReport.h"
#include "spds/SyncManager.h"
#include "spds/spdsutils.h"
#include "spds/SyncMLBuilder.h"

USE_NAMESPACE

#define TEST_SERVER_URL   "http://my.funambol/sync"

#ifdef _WIN32
# define TESTDIR "."
#else
# define TESTDIR "testcases"
#endif

class ServerDevInfTest : public CppUnit::TestFixture {

    CPPUNIT_TEST_SUITE(ServerDevInfTest);

        CPPUNIT_TEST(testAskServerDevInf);
        CPPUNIT_TEST(testPrepareServerDevInf);
        CPPUNIT_TEST(testFormatServerDevInf);
        CPPUNIT_TEST(testProcessServerDevInf1);
        CPPUNIT_TEST(testProcessServerDevInf2);

    CPPUNIT_TEST_SUITE_END();

public:
    void setUp() {

        report.setSyncSourceReports(config);

    }

    void tearDown() {

    }

private:

    SyncManagerConfig config;
    SyncReport report;

    //
    // Test: syncManager::askServerDevInf()
    // ------------------------------------
    void testAskServerDevInf() {

        bool ret = false;
        SyncManager syncManager(config, report);

        // Server url unchanged for tests 1. 2. 3.
        config.setSyncURL          (TEST_SERVER_URL);
        config.setServerLastSyncURL(TEST_SERVER_URL);

        // 1. No Server swv available in config: expect true
        config.setForceServerDevInfo(false);
        config.setServerSwv("");
        ret = syncManager.askServerDevInf();
        CPPUNIT_ASSERT(ret);

        // 2. Server swv available in config: expect false
        config.setForceServerDevInfo(false);
        config.setServerSwv("8.0.0");
        ret = syncManager.askServerDevInf();
        CPPUNIT_ASSERT(!ret);

        // 3. Force it via the config flag: expect true
        config.setForceServerDevInfo(true);
        config.setServerSwv("8.0.0");
        ret = syncManager.askServerDevInf();
        CPPUNIT_ASSERT(ret);

        // 4. Change the server URL: expect true
        config.setForceServerDevInfo(false);
        config.setServerSwv("8.0.0");
        StringBuffer urlModified = config.getSyncURL();
        urlModified.append("_mod");
        config.setServerLastSyncURL(urlModified.c_str());
        ret = syncManager.askServerDevInf();
        CPPUNIT_ASSERT(ret);
    }

    //
    // Test: syncMLBuilder::prepareServerDevInf()
    // ------------------------------------------
    void testPrepareServerDevInf() {

        SyncMLBuilder syncMLBuilder;
        AbstractCommand* command = syncMLBuilder.prepareServerDevInf();
        CPPUNIT_ASSERT(command);

        // Check it's a Get
        StringBuffer name = command->getName();
        CPPUNIT_ASSERT(name == GET);
        Get* get = (Get*)command;
        CPPUNIT_ASSERT(get);

        // Check the meta type = "application/vnd.syncml-devinf+xml"
        Meta* meta = get->getMeta();
        CPPUNIT_ASSERT(meta);
        StringBuffer type = meta->getType();
        CPPUNIT_ASSERT(type == DEVINF_FORMAT);

        ArrayList* items = get->getItems();
        CPPUNIT_ASSERT(items);

        // Expect only 1 item
        CPPUNIT_ASSERT_EQUAL(1, items->size());
        Item* item = (Item*)items->get(0);
        CPPUNIT_ASSERT(item);

        // Check the target locURI = "./devinf12"
        Target* target = item->getTarget();
        CPPUNIT_ASSERT(target);

        StringBuffer locURI = target->getLocURI();
        CPPUNIT_ASSERT(locURI == DEVINF_URI);

        delete command;
    }

    //
    // Test: format the Get command to obtain the Server capabilities
    // --------------------------------------------------------------
    void testFormatServerDevInf() {

        SyncMLBuilder syncMLBuilder;
        ArrayList commands;
        AbstractCommand* get = syncMLBuilder.prepareServerDevInf();
        CPPUNIT_ASSERT(get);

        commands.add(*get);
        delete get;
        SyncML* syncml = syncMLBuilder.prepareInitObject(NULL, NULL, &commands);
        CPPUNIT_ASSERT(syncml);

        char* msg = syncMLBuilder.prepareMsg(syncml);
        CPPUNIT_ASSERT(msg);

        // Check if this part of XML is included in the SyncML msg
        int cmdID = 1;
        StringBuffer expected;
        expected.sprintf("<Get><CmdID>%d</CmdID><Meta><Type xmlns=\"syncml:metinf\">%s</Type></Meta><Item><Target><LocURI>%s</LocURI></Target></Item></Get>",
                         cmdID, DEVINF_FORMAT, DEVINF_URI);

        StringBuffer syncmlMsg(msg);
        syncmlMsg.replaceAll("\n","");
        size_t pos = syncmlMsg.find(expected);
        CPPUNIT_ASSERT(pos != StringBuffer::npos);

        delete [] msg;
        deleteSyncML(&syncml);
    }

    //
    // Test: syncMLProcessor::processServerDevInf()
    // This is a sample XML with devInf Results from Funambol Server
    // -------------------------------------------------------------
    void testProcessServerDevInf1() {

        // Load and parse the sample XML with <Results> command from Server
        config.setSyncURL(TEST_SERVER_URL);
        processDevInf("devInfResults.xml");

        // Check the config has been filled as expected
        StringBuffer url1 = config.getSyncURL();
        StringBuffer url2 = config.getServerLastSyncURL();
        CPPUNIT_ASSERT(url1 == url2);

        int  iVal;
        bool bVal;
        StringBuffer value;
        value = config.getServerSwv();           CPPUNIT_ASSERT(value == "7.1.1");
        value = config.getServerFwv();           CPPUNIT_ASSERT(value == "-");
        value = config.getServerHwv();           CPPUNIT_ASSERT(value == "-");
        value = config.getServerMan();           CPPUNIT_ASSERT(value == "Funambol");
        value = config.getServerMod();           CPPUNIT_ASSERT(value == "DS Server ComEd");
        value = config.getServerOem();           CPPUNIT_ASSERT(value == "-");
        value = config.getServerDevID();         CPPUNIT_ASSERT(value == "funambol");
        value = config.getServerDevType();       CPPUNIT_ASSERT(value == "server");
        value = config.getServerVerDTD();        CPPUNIT_ASSERT(value == "1.2");
        bVal  = config.getServerUtc();           CPPUNIT_ASSERT(bVal  == true);
        bVal  = config.getServerLoSupport();     CPPUNIT_ASSERT(bVal  == true);
        bVal  = config.getServerNocSupport();    CPPUNIT_ASSERT(bVal  == true);
        iVal  = config.getServerSmartSlowSync(); CPPUNIT_ASSERT(iVal  == 1);

    }

    //
    // Test: syncMLProcessor::processServerDevInf()
    // This is a sample XML with devInf Results from OMA specs
    // -------------------------------------------------------
    void testProcessServerDevInf2() {

        // Load and parse the sample XML with <Results> command from Server
        config.setSyncURL(TEST_SERVER_URL);
        processDevInf("devInfResults2.xml");

        // Check the config has been filled as expected
        StringBuffer url1 = config.getSyncURL();
        StringBuffer url2 = config.getServerLastSyncURL();
        CPPUNIT_ASSERT(url1 == url2);

        int  iVal;
        bool bVal;
        StringBuffer value;
        value = config.getServerSwv();           CPPUNIT_ASSERT(value == "1.0.0");
        value = config.getServerFwv();           CPPUNIT_ASSERT(value == "1.0.1");
        value = config.getServerHwv();           CPPUNIT_ASSERT(value == "1.0.2");
        value = config.getServerMan();           CPPUNIT_ASSERT(value == "Small Factory, Ltd.");
        value = config.getServerMod();           CPPUNIT_ASSERT(value == "Tiny Server");
        value = config.getServerOem();           CPPUNIT_ASSERT(value == "Tiny Shop");
        value = config.getServerDevID();         CPPUNIT_ASSERT(value == "485749KR");
        value = config.getServerDevType();       CPPUNIT_ASSERT(value == "Server");
        value = config.getServerVerDTD();        CPPUNIT_ASSERT(value == "1.2");
        bVal  = config.getServerUtc();           CPPUNIT_ASSERT(bVal  == true);
        bVal  = config.getServerLoSupport();     CPPUNIT_ASSERT(bVal  == true);
        bVal  = config.getServerNocSupport();    CPPUNIT_ASSERT(bVal  == true);
        iVal  = config.getServerSmartSlowSync(); CPPUNIT_ASSERT(iVal  == 0);
    }

    /**
     * Utility: will process Server devInf from file 'filename',
     * store data in the config
     */
    void processDevInf(const StringBuffer& filename) {

        StringBuffer xml;
        loadTestFile(filename.c_str(), xml);

        ArrayList commands;
        Parser::getCommands(commands, xml);
        CPPUNIT_ASSERT_MESSAGE("Failed to parse devInf Results", (commands.size() == 1) );

        // Process the Server devInf
        SyncMLProcessor syncMLProcessor;
        AbstractCommand* cmd = (AbstractCommand*)commands.get(0);
        bool found = syncMLProcessor.processServerDevInf(cmd, config);
        CPPUNIT_ASSERT(found);
    }

    /**
     * Load a SyncML message from file, parse and reformat it
     * and return the original message and the converted one.
     */
    void loadTestFile(const char* fileName, StringBuffer& ret) {
        char*       message;
        size_t      len;

        StringBuffer path;
        path.sprintf("%s/%s", TESTDIR, fileName);

        bool fileLoaded = readFile(path, &message, &len, false);
        CPPUNIT_ASSERT_MESSAGE("Failed to load XML", fileLoaded);

        ret = message;
        delete [] message;
    }

};

CPPUNIT_TEST_SUITE_REGISTRATION( ServerDevInfTest );
<|endoftext|>