<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2011 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  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
//
//  Current versions can be found at www.libavg.de
//

#include "VideoInfo.h"

#include "../base/Exception.h"

namespace avg {

using namespace std;

VideoInfo::VideoInfo()
{
}

VideoInfo::VideoInfo(string sContainerFormat, float duration, int bitrate, bool bHasVideo,
        bool bHasAudio)
    : m_sContainerFormat(sContainerFormat),
      m_Duration(duration),
      m_Bitrate(bitrate),
      m_bHasVideo(bHasVideo),
      m_bHasAudio(bHasAudio)
{
}

void VideoInfo::setVideoData(const IntPoint& size, const string& sPixelFormat,
        int numFrames, float streamFPS, const string& sVCodec,
        bool bUsesVDPAU, float duration)
{
    AVG_ASSERT(m_bHasVideo);
    m_Size = size;
    m_sPixelFormat = sPixelFormat;
    m_NumFrames = numFrames;
    m_StreamFPS = streamFPS;
    m_sVCodec = sVCodec;
    m_bUsesVDPAU = bUsesVDPAU;
    m_VideoDuration = duration;
}

void VideoInfo::setAudioData(const string& sACodec, int sampleRate, int numAudioChannels,
        float duration)
{
    AVG_ASSERT(m_bHasAudio);
    m_sACodec = sACodec;
    m_SampleRate = sampleRate;
    m_NumAudioChannels = numAudioChannels;
    m_AudioDuration = duration;
}

float getStreamFPS(AVStream* pStream)
{
    float fps;
    if (pStream->avg_frame_rate.den != 0) {
        fps = float(av_q2d(pStream->avg_frame_rate));
    } else {
        if (pStream->r_frame_rate.den != 0) {
            fps = float(av_q2d(pStream->r_frame_rate));
        } else {
            float duration = float(pStream->duration)*float(av_q2d(pStream->time_base));
            fps = pStream->nb_frames/duration;
        }
    }
    AVG_ASSERT(fps < 10000);
/*
    cerr << "getStreamFPS: fps= " << fps << endl;
    cerr << "    r_frame_rate num: " << m_pVStream->r_frame_rate.num << ", den: " << m_pVStream->r_frame_rate.den << endl;
    cerr << "    avg_frame_rate: num: " << m_pVStream->avg_frame_rate.num << ", den: " << m_pVStream->avg_frame_rate.den << endl;
    cerr << "    numFrames= " << getNumFrames() << ", duration= "
                << getDuration(SS_VIDEO) << endl;
*/
    return fps;
}

}
<commit_msg>ffmpeg #ifdef hell.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2011 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  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
//
//  Current versions can be found at www.libavg.de
//

#include "VideoInfo.h"

#include "../base/Exception.h"

namespace avg {

using namespace std;

VideoInfo::VideoInfo()
{
}

VideoInfo::VideoInfo(string sContainerFormat, float duration, int bitrate, bool bHasVideo,
        bool bHasAudio)
    : m_sContainerFormat(sContainerFormat),
      m_Duration(duration),
      m_Bitrate(bitrate),
      m_bHasVideo(bHasVideo),
      m_bHasAudio(bHasAudio)
{
}

void VideoInfo::setVideoData(const IntPoint& size, const string& sPixelFormat,
        int numFrames, float streamFPS, const string& sVCodec,
        bool bUsesVDPAU, float duration)
{
    AVG_ASSERT(m_bHasVideo);
    m_Size = size;
    m_sPixelFormat = sPixelFormat;
    m_NumFrames = numFrames;
    m_StreamFPS = streamFPS;
    m_sVCodec = sVCodec;
    m_bUsesVDPAU = bUsesVDPAU;
    m_VideoDuration = duration;
}

void VideoInfo::setAudioData(const string& sACodec, int sampleRate, int numAudioChannels,
        float duration)
{
    AVG_ASSERT(m_bHasAudio);
    m_sACodec = sACodec;
    m_SampleRate = sampleRate;
    m_NumAudioChannels = numAudioChannels;
    m_AudioDuration = duration;
}

float getStreamFPS(AVStream* pStream)
{
    float fps;
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 42, 0)
    if (pStream->avg_frame_rate.den != 0) {
        fps = float(av_q2d(pStream->avg_frame_rate));
    } else {
#endif
        if (pStream->r_frame_rate.den != 0) {
            fps = float(av_q2d(pStream->r_frame_rate));
        } else {
            float duration = float(pStream->duration)*float(av_q2d(pStream->time_base));
            fps = pStream->nb_frames/duration;
        }
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 42, 0)
    }
#endif
    AVG_ASSERT(fps < 10000);
/*
    cerr << "getStreamFPS: fps= " << fps << endl;
    cerr << "    r_frame_rate num: " << m_pVStream->r_frame_rate.num << ", den: " << m_pVStream->r_frame_rate.den << endl;
    cerr << "    avg_frame_rate: num: " << m_pVStream->avg_frame_rate.num << ", den: " << m_pVStream->avg_frame_rate.den << endl;
    cerr << "    numFrames= " << getNumFrames() << ", duration= "
                << getDuration(SS_VIDEO) << endl;
*/
    return fps;
}

}
<|endoftext|>


<commit_before>#include "mbdb_record.h"

#include "mbdb_read.h"
#include "syscall_err.h"

#include <arpa/inet.h>
#include <fcntl.h>
#include <openssl/sha.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <vector>

template<typename T>
static void hash2str(const T hash, std::string& output)
{
  static const char* nibble2str = "0123456789abcdef";

  for (typename T::value_type tmp : hash) {
    output.push_back(nibble2str[tmp >> 4]);
    output.push_back(nibble2str[tmp & 0xf]);
  }
}

static std::string generate_storage_hash(const std::string& domain, const std::string& path)
{
  std::string   hash_input;
  unsigned char hash[SHA_DIGEST_LENGTH];
  std::string   hash_str;

  hash_input = domain + "-" + path;
  SHA1((unsigned char*) hash_input.c_str(), hash_input.size(), hash);
  hash2str(std::vector<uint8_t>(hash, hash + SHA_DIGEST_LENGTH), hash_str);

  return hash_str;
}

mbdb_record::mbdb_record(const char*& addr)
{
  std::vector<uint8_t>  tmp_hash;
  uint8_t               prop_count;
  std::string           unused_str;
  uint32_t              unused_u32;

  read<std::string>(addr, this->domain);
  read<std::string>(addr, this->path);
  read<std::string>(addr, this->link_target);

  read<std::vector<uint8_t>>(addr, tmp_hash);
  hash2str(tmp_hash, this->data_hash);

  read<std::string>(addr, unused_str);

  read<uint16_t>(addr, this->mode);
  read<uint32_t>(addr, unused_u32);
  read<uint32_t>(addr, unused_u32);
  read<uint32_t>(addr, this->uid);
  read<uint32_t>(addr, this->gid);
  read<uint32_t>(addr, this->mtime);
  read<uint32_t>(addr, this->atime);
  read<uint32_t>(addr, this->ctime);
  read<uint64_t>(addr, this->size);
  read<uint8_t>(addr, this->flag);

  read<uint8_t>(addr, prop_count);

  for (int i = 0; i < prop_count; ++i) {
    std::string name;
    std::string value;

    read<std::string>(addr, name);
    read<std::string>(addr, value);

    this->properties[name] = value;
  }

  this->storage_hash = generate_storage_hash(this->domain, this->path);
}

void mbdb_record::dump(std::ostream& out) const
{
  out << this->storage_hash << " " << this->domain << "/" << this->path << std::endl;
}

static bool extract_file(const std::string& out, const std::string& in, bool empty)
{
  bool    res = false;
  int     in_fd;
  int     out_fd;
  ssize_t size;
  char    buf[4096];

  if ((out_fd = SYSCALL_WARN(open, out.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1)
    goto cleanup_out;

  if (empty) {
    res = true;
    goto cleanup_out;
  }

  if ((in_fd = SYSCALL_WARN(open, in.c_str(), O_RDONLY)) == -1)
    goto cleanup_in;

  while ((size = read(in_fd, buf, sizeof buf)) > 0)
    write(out_fd, buf, size);

  res = true;

cleanup_in:
  close(in_fd);
cleanup_out:
  close(out_fd);

  return res;
}

static bool extract_dir(const std::string& out)
{
  return SYSCALL_WARN(mkdir, out.c_str(), 0777) == 0;
}

void mbdb_record::extract(const char* mbdb_dir) const
{
  bool        res = false;
  std::string target_path;

  target_path.reserve(this->domain.size() + sizeof '/' + this->path.size());
  target_path.append(this->domain);
  if (this->path.size() > 0) {
    target_path.append("/");
    target_path.append(this->path);
  }

  if (this->mode & S_IFREG) {
    std::string in_path;

    in_path.reserve(strlen(mbdb_dir) + sizeof '/' + 2 * SHA_DIGEST_LENGTH);
    in_path.append(mbdb_dir);
    in_path.append("/");
    in_path.append(this->storage_hash);

    res = extract_file(target_path, in_path, this->size == 0);
  } else if (this->mode & S_IFDIR) {
    res = extract_dir(target_path);
  }

  if (res) {
    SYSCALL_WARN(chmod, target_path.c_str(), this->mode & 0777);
  }
}
<commit_msg>Set atime/mtime during extraction.<commit_after>#include "mbdb_record.h"

#include "mbdb_read.h"
#include "syscall_err.h"

#include <arpa/inet.h>
#include <fcntl.h>
#include <openssl/sha.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#include <vector>

template<typename T>
static void hash2str(const T hash, std::string& output)
{
  static const char* nibble2str = "0123456789abcdef";

  for (typename T::value_type tmp : hash) {
    output.push_back(nibble2str[tmp >> 4]);
    output.push_back(nibble2str[tmp & 0xf]);
  }
}

static std::string generate_storage_hash(const std::string& domain, const std::string& path)
{
  std::string   hash_input;
  unsigned char hash[SHA_DIGEST_LENGTH];
  std::string   hash_str;

  hash_input = domain + "-" + path;
  SHA1((unsigned char*) hash_input.c_str(), hash_input.size(), hash);
  hash2str(std::vector<uint8_t>(hash, hash + SHA_DIGEST_LENGTH), hash_str);

  return hash_str;
}

mbdb_record::mbdb_record(const char*& addr)
{
  std::vector<uint8_t>  tmp_hash;
  uint8_t               prop_count;
  std::string           unused_str;
  uint32_t              unused_u32;

  read<std::string>(addr, this->domain);
  read<std::string>(addr, this->path);
  read<std::string>(addr, this->link_target);

  read<std::vector<uint8_t>>(addr, tmp_hash);
  hash2str(tmp_hash, this->data_hash);

  read<std::string>(addr, unused_str);

  read<uint16_t>(addr, this->mode);
  read<uint32_t>(addr, unused_u32);
  read<uint32_t>(addr, unused_u32);
  read<uint32_t>(addr, this->uid);
  read<uint32_t>(addr, this->gid);
  read<uint32_t>(addr, this->mtime);
  read<uint32_t>(addr, this->atime);
  read<uint32_t>(addr, this->ctime);
  read<uint64_t>(addr, this->size);
  read<uint8_t>(addr, this->flag);

  read<uint8_t>(addr, prop_count);

  for (int i = 0; i < prop_count; ++i) {
    std::string name;
    std::string value;

    read<std::string>(addr, name);
    read<std::string>(addr, value);

    this->properties[name] = value;
  }

  this->storage_hash = generate_storage_hash(this->domain, this->path);
}

void mbdb_record::dump(std::ostream& out) const
{
  out << this->storage_hash << " " << this->domain << "/" << this->path << std::endl;
}

static bool extract_file(const std::string& out, const std::string& in, bool empty)
{
  bool    res = false;
  int     in_fd;
  int     out_fd;
  ssize_t size;
  char    buf[4096];

  if ((out_fd = SYSCALL_WARN(open, out.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1)
    goto cleanup_out;

  if (empty) {
    res = true;
    goto cleanup_out;
  }

  if ((in_fd = SYSCALL_WARN(open, in.c_str(), O_RDONLY)) == -1)
    goto cleanup_in;

  while ((size = read(in_fd, buf, sizeof buf)) > 0)
    write(out_fd, buf, size);

  res = true;

cleanup_in:
  close(in_fd);
cleanup_out:
  close(out_fd);

  return res;
}

static bool extract_dir(const std::string& out)
{
  return SYSCALL_WARN(mkdir, out.c_str(), 0777) == 0;
}

void mbdb_record::extract(const char* mbdb_dir) const
{
  bool        res = false;
  std::string target_path;

  target_path.reserve(this->domain.size() + sizeof '/' + this->path.size());
  target_path.append(this->domain);
  if (this->path.size() > 0) {
    target_path.append("/");
    target_path.append(this->path);
  }

  if (this->mode & S_IFREG) {
    std::string in_path;

    in_path.reserve(strlen(mbdb_dir) + sizeof '/' + 2 * SHA_DIGEST_LENGTH);
    in_path.append(mbdb_dir);
    in_path.append("/");
    in_path.append(this->storage_hash);

    res = extract_file(target_path, in_path, this->size == 0);
  } else if (this->mode & S_IFDIR) {
    res = extract_dir(target_path);
  }

  if (res) {
    struct timeval times[2];

    times[0].tv_sec = this->atime;
    times[0].tv_usec = 0;
    times[1].tv_sec = this->mtime;
    times[1].tv_usec = 0;

    SYSCALL_WARN(chmod, target_path.c_str(), this->mode & 0777);
    SYSCALL_WARN(utimes, target_path.c_str(), times);
  }
}
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2014 Max-Planck-Institute for Intelligent Systems,
 *                     University of Southern California
 *    Jan Issac (jan.issac@gmail.com)
 *    Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 *
 *
 *  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 Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 */

/**
 * @date 2014
 * @author Jan Issac (jan.issac@gmail.com)
 * Max-Planck-Institute for Intelligent Systems,
 * University of Southern California
 */

#include <gtest/gtest.h>
#include "../typecast.hpp"

#include <Eigen/Dense>

#include <cmath>
#include <iostream>

#include <fl/util/math/linear_algebra.hpp>
#include <fl/filter/filter_interface.hpp>

#include <fl/filter/gaussian/gaussian_filter_linear.hpp>
#include <fl/model/process/linear_state_transition_model.hpp>
#include <fl/model/observation/linear_gaussian_observation_model.hpp>
#include <fl/model/observation/linear_decorrelated_gaussian_observation_model.hpp>

enum : signed int
{
    DecorrelatedGaussianModel,
    GaussianModel
};

static constexpr double epsilon = 0.1;

template <typename TestType>
class GaussianFilterLinearVsXTest
    : public ::testing::Test
{
protected:
    typedef typename TestType::Parameter Configuration;

    enum: signed int
    {
        StateDim = Configuration::StateDim,
        InputDim = Configuration::InputDim,
        ObsrvDim = Configuration::ObsrvDim,

        StateSize = fl::TestSize<StateDim, TestType>::Value,
        InputSize = fl::TestSize<InputDim, TestType>::Value,
        ObsrvSize = fl::TestSize<ObsrvDim, TestType>::Value
    };

    enum ModelSetup
    {
        Random,
        Identity
    };

    typedef Eigen::Matrix<fl::Real, StateSize, 1> State;
    typedef Eigen::Matrix<fl::Real, InputSize, 1> Input;
    typedef Eigen::Matrix<fl::Real, ObsrvSize, 1> Obsrv;

    typedef fl::IntegerTypeMap<
                fl::IntegerTypePair<
                    DecorrelatedGaussianModel,
                    fl::LinearDecorrelatedGaussianObservationModel<Obsrv, State>
                >,
                fl::IntegerTypePair<
                    GaussianModel,
                    fl::LinearGaussianObservationModel<Obsrv, State>
                >
            > ObsrvModelMap;

    typedef fl::LinearStateTransitionModel<State, Input> LinearStateTransition;

    typedef typename ObsrvModelMap::template Select<
                Configuration::SelectedModel
            >::Type LinearObservationModel;

    typedef fl::GaussianFilter<
                LinearStateTransition, LinearObservationModel
            > KalmanFilter;

    typedef typename Configuration::template FilterDefinition<
                LinearStateTransition,
                LinearObservationModel
            > FilterDefinition;

    typedef typename FilterDefinition::Type Filter;

    GaussianFilterLinearVsXTest()
        : predict_steps_(200),
          predict_update_steps_(30)
    { }

    KalmanFilter create_kalman_filter() const
    {
        return KalmanFilter(
                LinearStateTransition(StateDim, InputDim),
                LinearObservationModel(ObsrvDim, StateDim));
    }

    Filter create_filter() const
    {
        return Configuration::create_filter(
                LinearStateTransition(StateDim, InputDim),
                LinearObservationModel(ObsrvDim, StateDim));
    }

    void setup_models(
        KalmanFilter& kalman_filter, Filter& other_filter, ModelSetup setup)
    {
        auto A = kalman_filter.process_model().create_dynamics_matrix();
        auto B = kalman_filter.process_model().create_input_matrix();
        auto Q = kalman_filter.process_model().create_noise_matrix();

        auto H = kalman_filter.obsrv_model().create_sensor_matrix();
        auto R = kalman_filter.obsrv_model().create_noise_matrix();

        Q.setZero();
        R.setZero();
        B.setZero();

        switch (setup)
        {
        case Random:
            A.diagonal().setRandom();
            H.diagonal().setRandom();
            Q.diagonal().setRandom(); Q *= Q.transpose().eval();
            R.diagonal().setRandom(); R *= R.transpose().eval();
            break;

        case Identity:
            A.setIdentity();
            H.setIdentity();
            Q.setIdentity();
            R.setIdentity();
            break;
        }

        kalman_filter.process_model().dynamics_matrix(A);
        kalman_filter.process_model().input_matrix(B);
        kalman_filter.process_model().noise_matrix(Q);
        kalman_filter.obsrv_model().sensor_matrix(H);
        kalman_filter.obsrv_model().noise_matrix(R);

        other_filter.process_model().dynamics_matrix(A);
        other_filter.process_model().input_matrix(B);
        other_filter.process_model().noise_matrix(Q);
        other_filter.obsrv_model().sensor_matrix(H);
        other_filter.obsrv_model().noise_matrix(R);
    }

    State zero_state() { return State::Zero(StateDim); }
    Input zero_input() { return Input::Zero(InputDim); }
    Obsrv zero_obsrv() { return Obsrv::Zero(ObsrvDim); }

    State rand_state() { return State::Random(StateDim); }
    Input rand_input() { return Input::Random(InputDim); }
    Obsrv rand_obsrv() { return Obsrv::Random(ObsrvDim); }

protected:
    int predict_steps_;
    int predict_update_steps_;
};

TYPED_TEST_CASE_P(GaussianFilterLinearVsXTest);

//TYPED_TEST_P(GaussianFilterLinearVsXTest, predict)
//{
//    typedef TestFixture This;

//    auto other_filter = This::create_filter();
//    auto kalman_filter = This::create_kalman_filter();

//    This::setup_models(kalman_filter, other_filter, This::Random);

//    auto belief_other = other_filter.create_belief();
//    auto belief_kf = kalman_filter.create_belief();

//    for (int i = 0; i < This::predict_steps_; ++i)
//    {
//        other_filter.predict(belief_other, This::zero_input(), belief_other);
//        kalman_filter.predict(belief_kf, This::zero_input(), belief_kf);

//        if (!fl::are_similar(belief_other.mean(), belief_kf.mean(), epsilon))
//        {
//            std::cout << "i = " << i << std::endl;
//            PV(belief_kf.mean());
//            PV(belief_other.mean());
//        }

//        if (!fl::are_similar(belief_other.covariance(), belief_kf.covariance(), epsilon))
//        {
//            std::cout << "i = " << i << std::endl;
//            PV(belief_kf.covariance());
//            PV(belief_other.covariance());
//        }

//        ASSERT_TRUE(
//            fl::are_similar(belief_other.mean(), belief_kf.mean(), epsilon));

//        ASSERT_TRUE(
//            fl::are_similar(belief_other.covariance(), belief_kf.covariance(), epsilon));
//    }

//    PV(belief_kf.mean());
//    PV(belief_other.mean());
//    PV(belief_kf.covariance());
//    PV(belief_other.covariance());
//}

TYPED_TEST_P(GaussianFilterLinearVsXTest, predict_and_update)
{
    typedef TestFixture This;

    auto other_filter = This::create_filter();
    auto kalman_filter = This::create_kalman_filter();

    This::setup_models(kalman_filter, other_filter, This::Random);

    auto belief_other = other_filter.create_belief();
    auto belief_kf = kalman_filter.create_belief();

    for (int i = 0; i < This::predict_update_steps_; ++i)
    {
        auto y = This::rand_obsrv();

        kalman_filter.predict(belief_kf, This::zero_input(), belief_kf);
        other_filter.predict(belief_other, This::zero_input(), belief_other);

        if (!fl::are_similar(belief_other.mean(), belief_kf.mean(), epsilon))
        {
            std::cout << "predict i = " << i << std::endl;
            PV(belief_kf.mean());
            PV(belief_other.mean());
        }

        if (!fl::are_similar(belief_other.covariance(), belief_kf.covariance(), epsilon))
        {
            std::cout << "predict i = " << i << std::endl;
            PV(belief_kf.covariance());
            PV(belief_other.covariance());
        }

        kalman_filter.update(belief_kf, y, belief_kf);
        other_filter.update(belief_other, y, belief_other);

        if (!fl::are_similar(belief_other.mean(), belief_kf.mean(), epsilon))
        {
            std::cout << "update i = " << i << std::endl;
            PV(belief_kf.mean());
            PV(belief_other.mean());
        }

        if (!fl::are_similar(belief_other.covariance(), belief_kf.covariance(), epsilon))
        {
            std::cout << "update i = " << i << std::endl;
            PV(belief_kf.covariance());
            PV(belief_other.covariance());
        }

        ASSERT_TRUE(
            fl::are_similar(belief_other.mean(), belief_kf.mean(), epsilon));

        ASSERT_TRUE(
            fl::are_similar(belief_other.covariance(), belief_kf.covariance(), epsilon));
    }

    PV(belief_kf.mean());
    PV(belief_other.mean());

    PV(belief_kf.covariance());
    PV(belief_other.covariance());

    std::cout << other_filter.name() << std::endl;
}

REGISTER_TYPED_TEST_CASE_P(GaussianFilterLinearVsXTest,
                           predict_and_update);
<commit_msg>output :lipstick:<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2014 Max-Planck-Institute for Intelligent Systems,
 *                     University of Southern California
 *    Jan Issac (jan.issac@gmail.com)
 *    Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 *
 *
 *  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 Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 */

/**
 * @date 2014
 * @author Jan Issac (jan.issac@gmail.com)
 * Max-Planck-Institute for Intelligent Systems,
 * University of Southern California
 */

#include <gtest/gtest.h>
#include "../typecast.hpp"

#include <Eigen/Dense>

#include <cmath>
#include <iostream>

#include <fl/util/math/linear_algebra.hpp>
#include <fl/filter/filter_interface.hpp>

#include <fl/filter/gaussian/gaussian_filter_linear.hpp>
#include <fl/model/process/linear_state_transition_model.hpp>
#include <fl/model/observation/linear_gaussian_observation_model.hpp>
#include <fl/model/observation/linear_decorrelated_gaussian_observation_model.hpp>

enum : signed int
{
    DecorrelatedGaussianModel,
    GaussianModel
};

static constexpr double epsilon = 0.1;

template <typename TestType>
class GaussianFilterLinearVsXTest
    : public ::testing::Test
{
protected:
    typedef typename TestType::Parameter Configuration;

    enum: signed int
    {
        StateDim = Configuration::StateDim,
        InputDim = Configuration::InputDim,
        ObsrvDim = Configuration::ObsrvDim,

        StateSize = fl::TestSize<StateDim, TestType>::Value,
        InputSize = fl::TestSize<InputDim, TestType>::Value,
        ObsrvSize = fl::TestSize<ObsrvDim, TestType>::Value
    };

    enum ModelSetup
    {
        Random,
        Identity
    };

    typedef Eigen::Matrix<fl::Real, StateSize, 1> State;
    typedef Eigen::Matrix<fl::Real, InputSize, 1> Input;
    typedef Eigen::Matrix<fl::Real, ObsrvSize, 1> Obsrv;

    typedef fl::IntegerTypeMap<
                fl::IntegerTypePair<
                    DecorrelatedGaussianModel,
                    fl::LinearDecorrelatedGaussianObservationModel<Obsrv, State>
                >,
                fl::IntegerTypePair<
                    GaussianModel,
                    fl::LinearGaussianObservationModel<Obsrv, State>
                >
            > ObsrvModelMap;

    typedef fl::LinearStateTransitionModel<State, Input> LinearStateTransition;

    typedef typename ObsrvModelMap::template Select<
                Configuration::SelectedModel
            >::Type LinearObservationModel;

    typedef fl::GaussianFilter<
                LinearStateTransition, LinearObservationModel
            > KalmanFilter;

    typedef typename Configuration::template FilterDefinition<
                LinearStateTransition,
                LinearObservationModel
            > FilterDefinition;

    typedef typename FilterDefinition::Type Filter;

    GaussianFilterLinearVsXTest()
        : predict_steps_(200),
          predict_update_steps_(30)
    { }

    KalmanFilter create_kalman_filter() const
    {
        return KalmanFilter(
                LinearStateTransition(StateDim, InputDim),
                LinearObservationModel(ObsrvDim, StateDim));
    }

    Filter create_filter() const
    {
        return Configuration::create_filter(
                LinearStateTransition(StateDim, InputDim),
                LinearObservationModel(ObsrvDim, StateDim));
    }

    void setup_models(
        KalmanFilter& kalman_filter, Filter& other_filter, ModelSetup setup)
    {
        auto A = kalman_filter.process_model().create_dynamics_matrix();
        auto B = kalman_filter.process_model().create_input_matrix();
        auto Q = kalman_filter.process_model().create_noise_matrix();

        auto H = kalman_filter.obsrv_model().create_sensor_matrix();
        auto R = kalman_filter.obsrv_model().create_noise_matrix();

        Q.setZero();
        R.setZero();
        B.setZero();

        switch (setup)
        {
        case Random:
            A.diagonal().setRandom();
            H.diagonal().setRandom();
            Q.diagonal().setRandom(); Q *= Q.transpose().eval();
            R.diagonal().setRandom(); R *= R.transpose().eval();
            break;

        case Identity:
            A.setIdentity();
            H.setIdentity();
            Q.setIdentity();
            R.setIdentity();
            break;
        }

        kalman_filter.process_model().dynamics_matrix(A);
        kalman_filter.process_model().input_matrix(B);
        kalman_filter.process_model().noise_matrix(Q);
        kalman_filter.obsrv_model().sensor_matrix(H);
        kalman_filter.obsrv_model().noise_matrix(R);

        other_filter.process_model().dynamics_matrix(A);
        other_filter.process_model().input_matrix(B);
        other_filter.process_model().noise_matrix(Q);
        other_filter.obsrv_model().sensor_matrix(H);
        other_filter.obsrv_model().noise_matrix(R);
    }

    State zero_state() { return State::Zero(StateDim); }
    Input zero_input() { return Input::Zero(InputDim); }
    Obsrv zero_obsrv() { return Obsrv::Zero(ObsrvDim); }

    State rand_state() { return State::Random(StateDim); }
    Input rand_input() { return Input::Random(InputDim); }
    Obsrv rand_obsrv() { return Obsrv::Random(ObsrvDim); }

protected:
    int predict_steps_;
    int predict_update_steps_;
};

TYPED_TEST_CASE_P(GaussianFilterLinearVsXTest);

//TYPED_TEST_P(GaussianFilterLinearVsXTest, predict)
//{
//    typedef TestFixture This;

//    auto other_filter = This::create_filter();
//    auto kalman_filter = This::create_kalman_filter();

//    This::setup_models(kalman_filter, other_filter, This::Random);

//    auto belief_other = other_filter.create_belief();
//    auto belief_kf = kalman_filter.create_belief();

//    for (int i = 0; i < This::predict_steps_; ++i)
//    {
//        other_filter.predict(belief_other, This::zero_input(), belief_other);
//        kalman_filter.predict(belief_kf, This::zero_input(), belief_kf);

//        if (!fl::are_similar(belief_other.mean(), belief_kf.mean(), epsilon))
//        {
//            std::cout << "i = " << i << std::endl;
//            PV(belief_kf.mean());
//            PV(belief_other.mean());
//        }

//        if (!fl::are_similar(belief_other.covariance(), belief_kf.covariance(), epsilon))
//        {
//            std::cout << "i = " << i << std::endl;
//            PV(belief_kf.covariance());
//            PV(belief_other.covariance());
//        }

//        ASSERT_TRUE(
//            fl::are_similar(belief_other.mean(), belief_kf.mean(), epsilon));

//        ASSERT_TRUE(
//            fl::are_similar(belief_other.covariance(), belief_kf.covariance(), epsilon));
//    }

//    PV(belief_kf.mean());
//    PV(belief_other.mean());
//    PV(belief_kf.covariance());
//    PV(belief_other.covariance());
//}

TYPED_TEST_P(GaussianFilterLinearVsXTest, predict_and_update)
{
    typedef TestFixture This;

    auto other_filter = This::create_filter();
    auto kalman_filter = This::create_kalman_filter();

    This::setup_models(kalman_filter, other_filter, This::Random);

    auto belief_other = other_filter.create_belief();
    auto belief_kf = kalman_filter.create_belief();

    for (int i = 0; i < This::predict_update_steps_; ++i)
    {
        auto y = This::rand_obsrv();

        kalman_filter.predict(belief_kf, This::zero_input(), belief_kf);
        other_filter.predict(belief_other, This::zero_input(), belief_other);

//        if (!fl::are_similar(belief_other.mean(), belief_kf.mean(), epsilon))
//        {
//            std::cout << "predict i = " << i << std::endl;
//            PV(belief_kf.mean());
//            PV(belief_other.mean());
//        }

//        if (!fl::are_similar(belief_other.covariance(), belief_kf.covariance(), epsilon))
//        {
//            std::cout << "predict i = " << i << std::endl;
//            PV(belief_kf.covariance());
//            PV(belief_other.covariance());
//        }

        kalman_filter.update(belief_kf, y, belief_kf);
        other_filter.update(belief_other, y, belief_other);

//        if (!fl::are_similar(belief_other.mean(), belief_kf.mean(), epsilon))
//        {
//            std::cout << "update i = " << i << std::endl;
//            PV(belief_kf.mean());
//            PV(belief_other.mean());
//        }

//        if (!fl::are_similar(belief_other.covariance(), belief_kf.covariance(), epsilon))
//        {
//            std::cout << "update i = " << i << std::endl;
//            PV(belief_kf.covariance());
//            PV(belief_other.covariance());
//        }

        ASSERT_TRUE(
            fl::are_similar(belief_other.mean(), belief_kf.mean(), epsilon));

        ASSERT_TRUE(
            fl::are_similar(belief_other.covariance(), belief_kf.covariance(), epsilon));
    }

//    PV(belief_kf.mean());
//    PV(belief_other.mean());

//    PV(belief_kf.covariance());
//    PV(belief_other.covariance());

//    std::cout << other_filter.name() << std::endl;
}

REGISTER_TYPED_TEST_CASE_P(GaussianFilterLinearVsXTest,
                           predict_and_update);
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Manasij Mukherjee  <manasij7479@gmail.com>
// author:  Vassil Vassilev <vvasilev@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"

#include "clang/Sema/Sema.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTContext.h" // for operator new[](unsigned long, ASTCtx..)
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Frontend/CompilerInstance.h"

#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/InterpreterCallbacks.h"
#include "cling/Interpreter/AutoloadCallback.h"
#include "cling/Interpreter/Transaction.h"
#include "DeclUnloader.h"

namespace {
  static const char annoTag[] = "$clingAutoload$";
  static const size_t lenAnnoTag = sizeof(annoTag) - 1;
}

using namespace clang;

namespace cling {

  void AutoloadCallback::report(clang::SourceLocation l, llvm::StringRef name,
                                llvm::StringRef header) {
    Sema& sema= m_Interpreter->getSema();

    unsigned id
      = sema.getDiagnostics().getCustomDiagID (DiagnosticsEngine::Level::Warning,
                                                 "Note: '%0' can be found in %1");
/*    unsigned idn //TODO: To be enabled after we have a way to get the full path
      = sema.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Level::Note,
                                                "Type : %0 , Full Path: %1")*/;

    if (header.startswith(llvm::StringRef(annoTag, lenAnnoTag)))
      sema.Diags.Report(l, id) << name << header.drop_front(lenAnnoTag);

  }

  bool AutoloadCallback::LookupObject (TagDecl *t) {
    if (m_ShowSuggestions && t->hasAttr<AnnotateAttr>())
      report(t->getLocation(),t->getNameAsString(),t->getAttr<AnnotateAttr>()->getAnnotation());
    return false;
  }

  class AutoloadingVisitor: public RecursiveASTVisitor<AutoloadingVisitor> {
  private:
    ///\brief Flag determining the visitor's actions. If true, register autoload
    /// entries, i.e. remember the connection between filename and the declaration
    /// that needs to be updated on #include of the filename.
    /// If false, react on an #include by adjusting the forward decls, e.g. by
    /// removing the default tremplate arguments (that will now be provided by
    /// the definition read from the include) and by removing enum declarations
    /// that would otherwise be duplicates.
    bool m_IsStoringState;
    bool m_IsAutloadEntry;  // True during the traversal of an explicitly annotated decl.
    AutoloadCallback::FwdDeclsMap* m_Map;
    clang::Preprocessor* m_PP;
    clang::Sema* m_Sema;
    const clang::FileEntry* m_PrevFE;
    std::string m_PrevFileName;
  private:
    bool IsAutoloadEntry(Decl *D) {
       AnnotateAttr* attr = D->getAttr<AnnotateAttr>();
       if (attr && !attr->isInherited()) {
         llvm::StringRef annotation = attr->getAnnotation();
         assert(!annotation.empty() && "Empty annotation!");
         if (annotation.startswith(llvm::StringRef(annoTag, lenAnnoTag))) {
            // autoload annotation.
            return true;
         }
       }
       return false;
    }

    void InsertIntoAutoloadingState (Decl* decl, llvm::StringRef annotation) {

      assert(!annotation.empty() && "Empty annotation!");
      if (!annotation.startswith(llvm::StringRef(annoTag, lenAnnoTag))) {
        // not an autoload annotation.
        return;
      }

      assert(m_PP);

      const FileEntry* FE = 0;
      SourceLocation fileNameLoc;
      bool isAngled = false;
      const DirectoryLookup* FromDir = 0;
      const FileEntry* FromFile = 0;
      const DirectoryLookup* CurDir = 0;
      llvm::StringRef FileName = annotation.drop_front(lenAnnoTag);
      if (FileName.equals(m_PrevFileName))
        FE = m_PrevFE;
      else {
        FE = m_PP->LookupFile(fileNameLoc, FileName, isAngled,
                              FromDir, FromFile, CurDir, /*SearchPath*/0,
                              /*RelativePath*/ 0, /*suggestedModule*/0,
                              /*SkipCache*/ false, /*OpenFile*/ false,
                              /*CacheFail*/ true);
        m_PrevFE = FE;
        m_PrevFileName = FileName;
      }

      if (FE) {
        auto& Vec = (*m_Map)[FE];
        Vec.push_back(decl);
      } else {
        llvm::errs()
          << "Error in cling::AutoloadingVisitor::InsertIntoAutoloadingState:\n"
          "   Missing FileEntry for " << FileName << "\n";
        if (NamedDecl* ND = dyn_cast<NamedDecl>(decl)) {
          llvm::errs() << "   requested to autoload type ";
          ND->getNameForDiagnostic(llvm::errs(),
                                   ND->getASTContext().getPrintingPolicy(),
                                   true /*qualified*/);
          llvm::errs() << "\n";
        }
      }
    }

  public:
    AutoloadingVisitor():
      m_IsStoringState(false), m_IsAutloadEntry(false), m_Map(0), m_PP(0),
      m_Sema(0), m_PrevFE(0)
    {}

    void RemoveDefaultArgsOf(Decl* D, Sema* S) {
      m_Sema = S;

      auto cursor = D->getMostRecentDecl();
      m_IsAutloadEntry = IsAutoloadEntry(cursor);
      TraverseDecl(cursor);
      while (cursor != D && (cursor = cursor->getPreviousDecl())) {
        m_IsAutloadEntry = IsAutoloadEntry(cursor);
        TraverseDecl(cursor);
      }
      m_IsAutloadEntry = false;
    }

    void TrackDefaultArgStateOf(Decl* D, AutoloadCallback::FwdDeclsMap& map,
                                Preprocessor& PP) {
      m_IsStoringState = true;
      m_Map = ↦
      m_PP = &PP;
      TraverseDecl(D);
      m_PP = 0;
      m_Map = 0;
      m_IsStoringState = false;
    }

    bool shouldVisitTemplateInstantiations() { return true; }

    bool VisitDecl(Decl* D) {
      if (!m_IsStoringState)
        return true;

      if (!D->hasAttr<AnnotateAttr>())
        return true;

      if (AnnotateAttr* attr = D->getAttr<AnnotateAttr>())
        if (!attr->isInherited())
           InsertIntoAutoloadingState(D, attr->getAnnotation());

      return true;
    }

    bool VisitCXXRecordDecl(CXXRecordDecl* D) {
      if (!D->hasAttr<AnnotateAttr>())
        return true;

      if (ClassTemplateDecl* TmplD = D->getDescribedClassTemplate())
        return VisitTemplateDecl(TmplD);
      return true;
    }

    bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl* D) {
      if (m_IsStoringState)
        return true;

      if (m_IsAutloadEntry) {
        if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
          D->removeDefaultArgument();
      } else {
        if (D->hasDefaultArgument() && D->defaultArgumentWasInherited())
          D->removeDefaultArgument();
      }
      return true;
    }

    bool VisitTemplateDecl(TemplateDecl* D) {
      if (D->getTemplatedDecl() &&
          !D->getTemplatedDecl()->hasAttr<AnnotateAttr>())
        return true;

      // If we have a definition we might be about to re-#include the
      // same header containing definition that was #included previously,
      // i.e. we might have multiple fwd decls for the same template.
      // DO NOT remove the defaults here; the definition needs to keep it.
      // (ROOT-7037)
      if (ClassTemplateDecl* CTD = dyn_cast<ClassTemplateDecl>(D))
        if (CXXRecordDecl* TemplatedD = CTD->getTemplatedDecl())
          if (TemplatedD->getDefinition())
            return true;

      for(auto P: D->getTemplateParameters()->asArray())
        TraverseDecl(P);
      return true;
    }

    bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl* D) {
      if (m_IsStoringState)
        return true;

      if (m_IsAutloadEntry) {
        if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
          D->removeDefaultArgument();
      } else {
        if (D->hasDefaultArgument() && D->defaultArgumentWasInherited())
          D->removeDefaultArgument();
      }
      return true;
    }

    bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl* D) {
      if (m_IsStoringState)
        return true;

      if (m_IsAutloadEntry) {
        if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
          D->removeDefaultArgument();
      } else {
        if (D->hasDefaultArgument() && D->defaultArgumentWasInherited())
          D->removeDefaultArgument();
      }
      return true;
    }

    bool VisitParmVarDecl(ParmVarDecl* D) {
      if (m_IsStoringState)
        return true;

      if (m_IsAutloadEntry) {
        if (D->hasDefaultArg() && !D->hasInheritedDefaultArg())
          D->setDefaultArg(nullptr);
      } else {
        if (D->hasDefaultArg() && D->hasInheritedDefaultArg())
          D->setDefaultArg(nullptr);
      }
      return true;
    }

    bool VisitEnumDecl(EnumDecl* D) {
      if (m_IsStoringState)
        return true;

      // Now that we will read the full enum, unload the forward decl.
      if (IsAutoloadEntry(D))
        UnloadDecl(m_Sema, D);
      return true;
    }
  };

  void AutoloadCallback::InclusionDirective(clang::SourceLocation HashLoc,
                          const clang::Token &IncludeTok,
                          llvm::StringRef FileName,
                          bool IsAngled,
                          clang::CharSourceRange FilenameRange,
                          const clang::FileEntry *File,
                          llvm::StringRef SearchPath,
                          llvm::StringRef RelativePath,
                          const clang::Module *Imported) {
    // If File is 0 this means that the #included file doesn't exist.
    if (!File)
      return;

    auto found = m_Map.find(File);
    if (found == m_Map.end())
     return; // nothing to do, file not referred in any annotation

    AutoloadingVisitor defaultArgsCleaner;
    for (auto D : found->second) {
      defaultArgsCleaner.RemoveDefaultArgsOf(D, &getInterpreter()->getSema());
    }
    // Don't need to keep track of cleaned up decls from file.
    m_Map.erase(found);
  }

  AutoloadCallback::~AutoloadCallback() {
  }

  void AutoloadCallback::TransactionCommitted(const Transaction &T) {
    if (T.decls_begin() == T.decls_end())
      return;
    if (T.decls_begin()->m_DGR.isNull())
      return;

    // The first decl must be
    //   extern int __Cling_Autoloading_Map;
    bool HaveAutoloadingMapMarker = false;
    for (auto I = T.decls_begin(), E = T.decls_end();
         !HaveAutoloadingMapMarker && I != E; ++I) {
      if (I->m_Call != cling::Transaction::kCCIHandleTopLevelDecl)
        return;
      for (auto&& D: I->m_DGR) {
        if (isa<EmptyDecl>(D))
          continue;
        else if (auto VD = dyn_cast<VarDecl>(D)) {
          HaveAutoloadingMapMarker
            = VD->hasExternalStorage() && VD->getIdentifier()
              && VD->getName().equals("__Cling_Autoloading_Map");
          if (!HaveAutoloadingMapMarker)
            return;
          break;
        } else
          return;
      }
    }

    if (!HaveAutoloadingMapMarker)
      return;

    AutoloadingVisitor defaultArgsStateCollector;
    Preprocessor& PP = m_Interpreter->getCI()->getPreprocessor();
    for (auto I = T.decls_begin(), E = T.decls_end(); I != E; ++I)
      for (auto&& D: I->m_DGR)
        defaultArgsStateCollector.TrackDefaultArgStateOf(D, m_Map, PP);
  }

} //end namespace cling
<commit_msg>In AutoloadingVisitor, do not (ever) traverse definitions.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Manasij Mukherjee  <manasij7479@gmail.com>
// author:  Vassil Vassilev <vvasilev@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"

#include "clang/Sema/Sema.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTContext.h" // for operator new[](unsigned long, ASTCtx..)
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Frontend/CompilerInstance.h"

#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/InterpreterCallbacks.h"
#include "cling/Interpreter/AutoloadCallback.h"
#include "cling/Interpreter/Transaction.h"
#include "DeclUnloader.h"

namespace {
  static const char annoTag[] = "$clingAutoload$";
  static const size_t lenAnnoTag = sizeof(annoTag) - 1;
}

using namespace clang;

namespace cling {

  void AutoloadCallback::report(clang::SourceLocation l, llvm::StringRef name,
                                llvm::StringRef header) {
    Sema& sema= m_Interpreter->getSema();

    unsigned id
      = sema.getDiagnostics().getCustomDiagID (DiagnosticsEngine::Level::Warning,
                                                 "Note: '%0' can be found in %1");
/*    unsigned idn //TODO: To be enabled after we have a way to get the full path
      = sema.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Level::Note,
                                                "Type : %0 , Full Path: %1")*/;

    if (header.startswith(llvm::StringRef(annoTag, lenAnnoTag)))
      sema.Diags.Report(l, id) << name << header.drop_front(lenAnnoTag);

  }

  bool AutoloadCallback::LookupObject (TagDecl *t) {
    if (m_ShowSuggestions && t->hasAttr<AnnotateAttr>())
      report(t->getLocation(),t->getNameAsString(),t->getAttr<AnnotateAttr>()->getAnnotation());
    return false;
  }

  class AutoloadingVisitor: public RecursiveASTVisitor<AutoloadingVisitor> {
  private:
    ///\brief Flag determining the visitor's actions. If true, register autoload
    /// entries, i.e. remember the connection between filename and the declaration
    /// that needs to be updated on #include of the filename.
    /// If false, react on an #include by adjusting the forward decls, e.g. by
    /// removing the default tremplate arguments (that will now be provided by
    /// the definition read from the include) and by removing enum declarations
    /// that would otherwise be duplicates.
    bool m_IsStoringState;
    bool m_IsAutloadEntry;  // True during the traversal of an explicitly annotated decl.
    AutoloadCallback::FwdDeclsMap* m_Map;
    clang::Preprocessor* m_PP;
    clang::Sema* m_Sema;
    const clang::FileEntry* m_PrevFE;
    std::string m_PrevFileName;
  private:
    bool IsAutoloadEntry(Decl *D) {
       AnnotateAttr* attr = D->getAttr<AnnotateAttr>();
       if (attr && !attr->isInherited()) {
         llvm::StringRef annotation = attr->getAnnotation();
         assert(!annotation.empty() && "Empty annotation!");
         if (annotation.startswith(llvm::StringRef(annoTag, lenAnnoTag))) {
            // autoload annotation.
            return true;
         }
       }
       return false;
    }

    void InsertIntoAutoloadingState (Decl* decl, llvm::StringRef annotation) {

      assert(!annotation.empty() && "Empty annotation!");
      if (!annotation.startswith(llvm::StringRef(annoTag, lenAnnoTag))) {
        // not an autoload annotation.
        return;
      }

      assert(m_PP);

      const FileEntry* FE = 0;
      SourceLocation fileNameLoc;
      bool isAngled = false;
      const DirectoryLookup* FromDir = 0;
      const FileEntry* FromFile = 0;
      const DirectoryLookup* CurDir = 0;
      llvm::StringRef FileName = annotation.drop_front(lenAnnoTag);
      if (FileName.equals(m_PrevFileName))
        FE = m_PrevFE;
      else {
        FE = m_PP->LookupFile(fileNameLoc, FileName, isAngled,
                              FromDir, FromFile, CurDir, /*SearchPath*/0,
                              /*RelativePath*/ 0, /*suggestedModule*/0,
                              /*SkipCache*/ false, /*OpenFile*/ false,
                              /*CacheFail*/ true);
        m_PrevFE = FE;
        m_PrevFileName = FileName;
      }

      if (FE) {
        auto& Vec = (*m_Map)[FE];
        Vec.push_back(decl);
      } else {
        llvm::errs()
          << "Error in cling::AutoloadingVisitor::InsertIntoAutoloadingState:\n"
          "   Missing FileEntry for " << FileName << "\n";
        if (NamedDecl* ND = dyn_cast<NamedDecl>(decl)) {
          llvm::errs() << "   requested to autoload type ";
          ND->getNameForDiagnostic(llvm::errs(),
                                   ND->getASTContext().getPrintingPolicy(),
                                   true /*qualified*/);
          llvm::errs() << "\n";
        }
      }
    }

  public:
    AutoloadingVisitor():
      m_IsStoringState(false), m_IsAutloadEntry(false), m_Map(0), m_PP(0),
      m_Sema(0), m_PrevFE(0)
    {}

    void RemoveDefaultArgsOf(Decl* D, Sema* S) {
      m_Sema = S;

      auto cursor = D->getMostRecentDecl();
      m_IsAutloadEntry = IsAutoloadEntry(cursor);
      TraverseDecl(cursor);
      while (cursor != D && (cursor = cursor->getPreviousDecl())) {
        m_IsAutloadEntry = IsAutoloadEntry(cursor);
        TraverseDecl(cursor);
      }
      m_IsAutloadEntry = false;
    }

    void TrackDefaultArgStateOf(Decl* D, AutoloadCallback::FwdDeclsMap& map,
                                Preprocessor& PP) {
      m_IsStoringState = true;
      m_Map = ↦
      m_PP = &PP;
      TraverseDecl(D);
      m_PP = 0;
      m_Map = 0;
      m_IsStoringState = false;
    }

    bool shouldVisitTemplateInstantiations() { return true; }

    bool VisitDecl(Decl* D) {
      if (!m_IsStoringState)
        return true;

      if (!D->hasAttr<AnnotateAttr>())
        return true;

      if (AnnotateAttr* attr = D->getAttr<AnnotateAttr>())
        if (!attr->isInherited())
           InsertIntoAutoloadingState(D, attr->getAnnotation());

      return true;
    }

    bool VisitCXXRecordDecl(CXXRecordDecl* D) {
      // Since we are only interested in fixing forward declaration
      // there is no need to continue on when we see a complete definition.
      if (D->isCompleteDefinition())
        return false;

      if (!D->hasAttr<AnnotateAttr>())
        return true;

      if (ClassTemplateDecl* TmplD = D->getDescribedClassTemplate())
        return VisitTemplateDecl(TmplD);
      return true;
    }

    bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl* D) {
      if (m_IsStoringState)
        return true;

      if (m_IsAutloadEntry) {
        if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
          D->removeDefaultArgument();
      } else {
        if (D->hasDefaultArgument() && D->defaultArgumentWasInherited())
          D->removeDefaultArgument();
      }
      return true;
    }

    bool VisitTemplateDecl(TemplateDecl* D) {
      if (D->getTemplatedDecl() &&
          !D->getTemplatedDecl()->hasAttr<AnnotateAttr>())
        return true;

      // If we have a definition we might be about to re-#include the
      // same header containing definition that was #included previously,
      // i.e. we might have multiple fwd decls for the same template.
      // DO NOT remove the defaults here; the definition needs to keep it.
      // (ROOT-7037)
      if (ClassTemplateDecl* CTD = dyn_cast<ClassTemplateDecl>(D))
        if (CXXRecordDecl* TemplatedD = CTD->getTemplatedDecl())
          if (TemplatedD->getDefinition())
            return true;

      for(auto P: D->getTemplateParameters()->asArray())
        TraverseDecl(P);
      return true;
    }

    bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl* D) {
      if (m_IsStoringState)
        return true;

      if (m_IsAutloadEntry) {
        if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
          D->removeDefaultArgument();
      } else {
        if (D->hasDefaultArgument() && D->defaultArgumentWasInherited())
          D->removeDefaultArgument();
      }
      return true;
    }

    bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl* D) {
      if (m_IsStoringState)
        return true;

      if (m_IsAutloadEntry) {
        if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
          D->removeDefaultArgument();
      } else {
        if (D->hasDefaultArgument() && D->defaultArgumentWasInherited())
          D->removeDefaultArgument();
      }
      return true;
    }

    bool VisitParmVarDecl(ParmVarDecl* D) {
      if (m_IsStoringState)
        return true;

      if (m_IsAutloadEntry) {
        if (D->hasDefaultArg() && !D->hasInheritedDefaultArg())
          D->setDefaultArg(nullptr);
      } else {
        if (D->hasDefaultArg() && D->hasInheritedDefaultArg())
          D->setDefaultArg(nullptr);
      }
      return true;
    }

    bool VisitEnumDecl(EnumDecl* D) {
      if (m_IsStoringState)
        return true;

      // Now that we will read the full enum, unload the forward decl.
      if (IsAutoloadEntry(D))
        UnloadDecl(m_Sema, D);
      return true;
    }
  };

  void AutoloadCallback::InclusionDirective(clang::SourceLocation HashLoc,
                          const clang::Token &IncludeTok,
                          llvm::StringRef FileName,
                          bool IsAngled,
                          clang::CharSourceRange FilenameRange,
                          const clang::FileEntry *File,
                          llvm::StringRef SearchPath,
                          llvm::StringRef RelativePath,
                          const clang::Module *Imported) {
    // If File is 0 this means that the #included file doesn't exist.
    if (!File)
      return;

    auto found = m_Map.find(File);
    if (found == m_Map.end())
     return; // nothing to do, file not referred in any annotation

    AutoloadingVisitor defaultArgsCleaner;
    for (auto D : found->second) {
      defaultArgsCleaner.RemoveDefaultArgsOf(D, &getInterpreter()->getSema());
    }
    // Don't need to keep track of cleaned up decls from file.
    m_Map.erase(found);
  }

  AutoloadCallback::~AutoloadCallback() {
  }

  void AutoloadCallback::TransactionCommitted(const Transaction &T) {
    if (T.decls_begin() == T.decls_end())
      return;
    if (T.decls_begin()->m_DGR.isNull())
      return;

    // The first decl must be
    //   extern int __Cling_Autoloading_Map;
    bool HaveAutoloadingMapMarker = false;
    for (auto I = T.decls_begin(), E = T.decls_end();
         !HaveAutoloadingMapMarker && I != E; ++I) {
      if (I->m_Call != cling::Transaction::kCCIHandleTopLevelDecl)
        return;
      for (auto&& D: I->m_DGR) {
        if (isa<EmptyDecl>(D))
          continue;
        else if (auto VD = dyn_cast<VarDecl>(D)) {
          HaveAutoloadingMapMarker
            = VD->hasExternalStorage() && VD->getIdentifier()
              && VD->getName().equals("__Cling_Autoloading_Map");
          if (!HaveAutoloadingMapMarker)
            return;
          break;
        } else
          return;
      }
    }

    if (!HaveAutoloadingMapMarker)
      return;

    AutoloadingVisitor defaultArgsStateCollector;
    Preprocessor& PP = m_Interpreter->getCI()->getPreprocessor();
    for (auto I = T.decls_begin(), E = T.decls_end(); I != E; ++I)
      for (auto&& D: I->m_DGR)
        defaultArgsStateCollector.TrackDefaultArgStateOf(D, m_Map, PP);
  }

} //end namespace cling
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                     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.
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++98, c++03, c++11, c++14

// <functional>

// template <class F, class ...Args>
// result_of_t<F&&(Args&&...)> invoke(F&&, Args&&...);

/// C++14 [func.def] 20.9.0
/// (1) The following definitions apply to this Clause:
/// (2) A call signature is the name of a return type followed by a parenthesized
///     comma-separated list of zero or more argument types.
/// (3) A callable type is a function object type (20.9) or a pointer to member.
/// (4) A callable object is an object of a callable type.
/// (5) A call wrapper type is a type that holds a callable object and supports
///     a call operation that forwards to that object.
/// (6) A call wrapper is an object of a call wrapper type.
/// (7) A target object is the callable object held by a call wrapper.

/// C++14 [func.require] 20.9.1
///
/// Define INVOKE (f, t1, t2, ..., tN) as follows:
///   (1.1) - (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of
///   type T or a reference to an object of type T or a reference to an object of a type derived from T;
///   (1.2) - ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of
///   the types described in the previous item;
///   (1.3) - t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is an object of type T or a
///   reference to an object of type T or a reference to an object of a type derived from T;
///   (1.4) - (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 is not one of the types
///   described in the previous item;
///   (1.5) - f(t1, t2, ..., tN) in all other cases.

#include <functional>
#include <type_traits>
#include <cassert>

struct NonCopyable {
    NonCopyable() {}
private:
    NonCopyable(NonCopyable const&) = delete;
    NonCopyable& operator=(NonCopyable const&) = delete;
};

struct TestClass {
    explicit TestClass(int x) : data(x) {}

    int& operator()(NonCopyable&&) & { return data; }
    int const& operator()(NonCopyable&&) const & { return data; }
    int volatile& operator()(NonCopyable&&) volatile & { return data; }
    int const volatile& operator()(NonCopyable&&) const volatile & { return data; }

    int&& operator()(NonCopyable&&) && { return std::move(data); }
    int const&& operator()(NonCopyable&&) const && { return std::move(data); }
    int volatile&& operator()(NonCopyable&&) volatile && { return std::move(data); }
    int const volatile&& operator()(NonCopyable&&) const volatile && { return std::move(data); }

    int data;
private:
    TestClass(TestClass const&) = delete;
    TestClass& operator=(TestClass const&) = delete;
};

struct DerivedFromTestClass : public TestClass {
    explicit DerivedFromTestClass(int x) : TestClass(x) {}
};

int& foo(NonCopyable&&) {
    static int data = 42;
    return data;
}

template <class Signature,  class Expect, class Functor>
void test_b12(Functor&& f) {
    // Create the callable object.
    typedef Signature TestClass::*ClassFunc;
    ClassFunc func_ptr = &TestClass::operator();

    // Create the dummy arg.
    NonCopyable arg;

    // Check that the deduced return type of invoke is what is expected.
    typedef decltype(
        std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg))
    ) DeducedReturnType;
    static_assert((std::is_same<DeducedReturnType, Expect>::value), "");

    // Check that result_of_t matches Expect.
    typedef typename std::result_of<ClassFunc&&(Functor&&, NonCopyable&&)>::type
      ResultOfReturnType;
    static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");

    // Run invoke and check the return value.
    DeducedReturnType ret =
            std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg));
    assert(ret == 42);
}

template <class Expect, class Functor>
void test_b34(Functor&& f) {
    // Create the callable object.
    typedef int TestClass::*ClassFunc;
    ClassFunc func_ptr = &TestClass::data;

    // Check that the deduced return type of invoke is what is expected.
    typedef decltype(
        std::invoke(func_ptr, std::forward<Functor>(f))
    ) DeducedReturnType;
    static_assert((std::is_same<DeducedReturnType, Expect>::value), "");

    // Check that result_of_t matches Expect.
    typedef typename std::result_of<ClassFunc&&(Functor&&)>::type
            ResultOfReturnType;
    static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");

    // Run invoke and check the return value.
    DeducedReturnType ret =
            std::invoke(func_ptr, std::forward<Functor>(f));
    assert(ret == 42);
}

template <class Expect, class Functor>
void test_b5(Functor&& f) {
    NonCopyable arg;

    // Check that the deduced return type of invoke is what is expected.
    typedef decltype(
        std::invoke(std::forward<Functor>(f), std::move(arg))
    ) DeducedReturnType;
    static_assert((std::is_same<DeducedReturnType, Expect>::value), "");

    // Check that result_of_t matches Expect.
    typedef typename std::result_of<Functor&&(NonCopyable&&)>::type
            ResultOfReturnType;
    static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");

    // Run invoke and check the return value.
    DeducedReturnType ret = std::invoke(std::forward<Functor>(f), std::move(arg));
    assert(ret == 42);
}

void bullet_one_two_tests() {
    {
        TestClass cl(42);
        test_b12<int&(NonCopyable&&) &, int&>(cl);
        test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
        test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
        test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);

        test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl));
        test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl));
        test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl));
        test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl));
    }
    {
        DerivedFromTestClass cl(42);
        test_b12<int&(NonCopyable&&) &, int&>(cl);
        test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
        test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
        test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);

        test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl));
        test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl));
        test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl));
        test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl));
    }
    {
        TestClass cl_obj(42);
        TestClass *cl = &cl_obj;
        test_b12<int&(NonCopyable&&) &, int&>(cl);
        test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
        test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
        test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
    }
    {
        DerivedFromTestClass cl_obj(42);
        DerivedFromTestClass *cl = &cl_obj;
        test_b12<int&(NonCopyable&&) &, int&>(cl);
        test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
        test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
        test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
    }
}

void bullet_three_four_tests() {
    {
        typedef TestClass Fn;
        Fn cl(42);
        test_b34<int&>(cl);
        test_b34<int const&>(static_cast<Fn const&>(cl));
        test_b34<int volatile&>(static_cast<Fn volatile&>(cl));
        test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl));

        test_b34<int&&>(static_cast<Fn &&>(cl));
        test_b34<int const&&>(static_cast<Fn const&&>(cl));
        test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl));
        test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
    }
    {
        typedef DerivedFromTestClass Fn;
        Fn cl(42);
        test_b34<int&>(cl);
        test_b34<int const&>(static_cast<Fn const&>(cl));
        test_b34<int volatile&>(static_cast<Fn volatile&>(cl));
        test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl));

        test_b34<int&&>(static_cast<Fn &&>(cl));
        test_b34<int const&&>(static_cast<Fn const&&>(cl));
        test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl));
        test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
    }
    {
        typedef TestClass Fn;
        Fn cl_obj(42);
        Fn* cl = &cl_obj;
        test_b34<int&>(cl);
        test_b34<int const&>(static_cast<Fn const*>(cl));
        test_b34<int volatile&>(static_cast<Fn volatile*>(cl));
        test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl));
    }
    {
        typedef DerivedFromTestClass Fn;
        Fn cl_obj(42);
        Fn* cl = &cl_obj;
        test_b34<int&>(cl);
        test_b34<int const&>(static_cast<Fn const*>(cl));
        test_b34<int volatile&>(static_cast<Fn volatile*>(cl));
        test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl));
    }
}

void bullet_five_tests() {
    using FooType = int&(NonCopyable&&);
    {
        FooType& fn = foo;
        test_b5<int &>(fn);
    }
    {
        FooType* fn = foo;
        test_b5<int &>(fn);
    }
    {
        typedef TestClass Fn;
        Fn cl(42);
        test_b5<int&>(cl);
        test_b5<int const&>(static_cast<Fn const&>(cl));
        test_b5<int volatile&>(static_cast<Fn volatile&>(cl));
        test_b5<int const volatile&>(static_cast<Fn const volatile &>(cl));

        test_b5<int&&>(static_cast<Fn &&>(cl));
        test_b5<int const&&>(static_cast<Fn const&&>(cl));
        test_b5<int volatile&&>(static_cast<Fn volatile&&>(cl));
        test_b5<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
    }
}

int main() {
    bullet_one_two_tests();
    bullet_three_four_tests();
    bullet_five_tests();
}
<commit_msg>Explicitly #include <utility> so that we get std::move. Thanks to Walter for the bug report.<commit_after>//===----------------------------------------------------------------------===//
//
//                     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.
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++98, c++03, c++11, c++14

// <functional>

// template <class F, class ...Args>
// result_of_t<F&&(Args&&...)> invoke(F&&, Args&&...);

/// C++14 [func.def] 20.9.0
/// (1) The following definitions apply to this Clause:
/// (2) A call signature is the name of a return type followed by a parenthesized
///     comma-separated list of zero or more argument types.
/// (3) A callable type is a function object type (20.9) or a pointer to member.
/// (4) A callable object is an object of a callable type.
/// (5) A call wrapper type is a type that holds a callable object and supports
///     a call operation that forwards to that object.
/// (6) A call wrapper is an object of a call wrapper type.
/// (7) A target object is the callable object held by a call wrapper.

/// C++14 [func.require] 20.9.1
///
/// Define INVOKE (f, t1, t2, ..., tN) as follows:
///   (1.1) - (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of
///   type T or a reference to an object of type T or a reference to an object of a type derived from T;
///   (1.2) - ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of
///   the types described in the previous item;
///   (1.3) - t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is an object of type T or a
///   reference to an object of type T or a reference to an object of a type derived from T;
///   (1.4) - (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 is not one of the types
///   described in the previous item;
///   (1.5) - f(t1, t2, ..., tN) in all other cases.

#include <functional>
#include <type_traits>
#include <utilty> // for std::move
#include <cassert>

struct NonCopyable {
    NonCopyable() {}
private:
    NonCopyable(NonCopyable const&) = delete;
    NonCopyable& operator=(NonCopyable const&) = delete;
};

struct TestClass {
    explicit TestClass(int x) : data(x) {}

    int& operator()(NonCopyable&&) & { return data; }
    int const& operator()(NonCopyable&&) const & { return data; }
    int volatile& operator()(NonCopyable&&) volatile & { return data; }
    int const volatile& operator()(NonCopyable&&) const volatile & { return data; }

    int&& operator()(NonCopyable&&) && { return std::move(data); }
    int const&& operator()(NonCopyable&&) const && { return std::move(data); }
    int volatile&& operator()(NonCopyable&&) volatile && { return std::move(data); }
    int const volatile&& operator()(NonCopyable&&) const volatile && { return std::move(data); }

    int data;
private:
    TestClass(TestClass const&) = delete;
    TestClass& operator=(TestClass const&) = delete;
};

struct DerivedFromTestClass : public TestClass {
    explicit DerivedFromTestClass(int x) : TestClass(x) {}
};

int& foo(NonCopyable&&) {
    static int data = 42;
    return data;
}

template <class Signature,  class Expect, class Functor>
void test_b12(Functor&& f) {
    // Create the callable object.
    typedef Signature TestClass::*ClassFunc;
    ClassFunc func_ptr = &TestClass::operator();

    // Create the dummy arg.
    NonCopyable arg;

    // Check that the deduced return type of invoke is what is expected.
    typedef decltype(
        std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg))
    ) DeducedReturnType;
    static_assert((std::is_same<DeducedReturnType, Expect>::value), "");

    // Check that result_of_t matches Expect.
    typedef typename std::result_of<ClassFunc&&(Functor&&, NonCopyable&&)>::type
      ResultOfReturnType;
    static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");

    // Run invoke and check the return value.
    DeducedReturnType ret =
            std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg));
    assert(ret == 42);
}

template <class Expect, class Functor>
void test_b34(Functor&& f) {
    // Create the callable object.
    typedef int TestClass::*ClassFunc;
    ClassFunc func_ptr = &TestClass::data;

    // Check that the deduced return type of invoke is what is expected.
    typedef decltype(
        std::invoke(func_ptr, std::forward<Functor>(f))
    ) DeducedReturnType;
    static_assert((std::is_same<DeducedReturnType, Expect>::value), "");

    // Check that result_of_t matches Expect.
    typedef typename std::result_of<ClassFunc&&(Functor&&)>::type
            ResultOfReturnType;
    static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");

    // Run invoke and check the return value.
    DeducedReturnType ret =
            std::invoke(func_ptr, std::forward<Functor>(f));
    assert(ret == 42);
}

template <class Expect, class Functor>
void test_b5(Functor&& f) {
    NonCopyable arg;

    // Check that the deduced return type of invoke is what is expected.
    typedef decltype(
        std::invoke(std::forward<Functor>(f), std::move(arg))
    ) DeducedReturnType;
    static_assert((std::is_same<DeducedReturnType, Expect>::value), "");

    // Check that result_of_t matches Expect.
    typedef typename std::result_of<Functor&&(NonCopyable&&)>::type
            ResultOfReturnType;
    static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");

    // Run invoke and check the return value.
    DeducedReturnType ret = std::invoke(std::forward<Functor>(f), std::move(arg));
    assert(ret == 42);
}

void bullet_one_two_tests() {
    {
        TestClass cl(42);
        test_b12<int&(NonCopyable&&) &, int&>(cl);
        test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
        test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
        test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);

        test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl));
        test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl));
        test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl));
        test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl));
    }
    {
        DerivedFromTestClass cl(42);
        test_b12<int&(NonCopyable&&) &, int&>(cl);
        test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
        test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
        test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);

        test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl));
        test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl));
        test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl));
        test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl));
    }
    {
        TestClass cl_obj(42);
        TestClass *cl = &cl_obj;
        test_b12<int&(NonCopyable&&) &, int&>(cl);
        test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
        test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
        test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
    }
    {
        DerivedFromTestClass cl_obj(42);
        DerivedFromTestClass *cl = &cl_obj;
        test_b12<int&(NonCopyable&&) &, int&>(cl);
        test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
        test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
        test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
    }
}

void bullet_three_four_tests() {
    {
        typedef TestClass Fn;
        Fn cl(42);
        test_b34<int&>(cl);
        test_b34<int const&>(static_cast<Fn const&>(cl));
        test_b34<int volatile&>(static_cast<Fn volatile&>(cl));
        test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl));

        test_b34<int&&>(static_cast<Fn &&>(cl));
        test_b34<int const&&>(static_cast<Fn const&&>(cl));
        test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl));
        test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
    }
    {
        typedef DerivedFromTestClass Fn;
        Fn cl(42);
        test_b34<int&>(cl);
        test_b34<int const&>(static_cast<Fn const&>(cl));
        test_b34<int volatile&>(static_cast<Fn volatile&>(cl));
        test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl));

        test_b34<int&&>(static_cast<Fn &&>(cl));
        test_b34<int const&&>(static_cast<Fn const&&>(cl));
        test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl));
        test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
    }
    {
        typedef TestClass Fn;
        Fn cl_obj(42);
        Fn* cl = &cl_obj;
        test_b34<int&>(cl);
        test_b34<int const&>(static_cast<Fn const*>(cl));
        test_b34<int volatile&>(static_cast<Fn volatile*>(cl));
        test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl));
    }
    {
        typedef DerivedFromTestClass Fn;
        Fn cl_obj(42);
        Fn* cl = &cl_obj;
        test_b34<int&>(cl);
        test_b34<int const&>(static_cast<Fn const*>(cl));
        test_b34<int volatile&>(static_cast<Fn volatile*>(cl));
        test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl));
    }
}

void bullet_five_tests() {
    using FooType = int&(NonCopyable&&);
    {
        FooType& fn = foo;
        test_b5<int &>(fn);
    }
    {
        FooType* fn = foo;
        test_b5<int &>(fn);
    }
    {
        typedef TestClass Fn;
        Fn cl(42);
        test_b5<int&>(cl);
        test_b5<int const&>(static_cast<Fn const&>(cl));
        test_b5<int volatile&>(static_cast<Fn volatile&>(cl));
        test_b5<int const volatile&>(static_cast<Fn const volatile &>(cl));

        test_b5<int&&>(static_cast<Fn &&>(cl));
        test_b5<int const&&>(static_cast<Fn const&&>(cl));
        test_b5<int volatile&&>(static_cast<Fn volatile&&>(cl));
        test_b5<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
    }
}

int main() {
    bullet_one_two_tests();
    bullet_three_four_tests();
    bullet_five_tests();
}
<|endoftext|>


<commit_before>
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "Test.h"
#include "SkChecksum.h"
#include "SkConsistentChecksum.h"

namespace skiatest {
    class ChecksumTestClass : public Test {
    public:
        static Test* Factory(void*) {return SkNEW(ChecksumTestClass); }
    protected:
        virtual void onGetName(SkString* name) { name->set("Checksum"); }
        virtual void onRun(Reporter* reporter) {
            this->fReporter = reporter;
            RunTest();
        }
    private:
        enum Algorithm {
            kSkChecksum,
            kSkConsistentChecksum
        };

        // Call Compute(data, size) on the appropriate checksum algorithm,
        // depending on this->fWhichAlgorithm.
        uint32_t ComputeChecksum(uint32_t* data, size_t size) {
            // Our checksum algorithms require 32-bit aligned data.
            // If either of these tests fail, then the algorithm
            // doesn't have a chance.
            REPORTER_ASSERT_MESSAGE(fReporter,
                                    reinterpret_cast<uintptr_t>(data) % 4 == 0,
                                    "test data pointer is not 32-bit aligned");
            REPORTER_ASSERT_MESSAGE(fReporter, SkIsAlign4(size),
                                    "test data size is not 32-bit aligned");

            switch(fWhichAlgorithm) {
            case kSkChecksum:
                return SkChecksum::Compute(data, size);
            case kSkConsistentChecksum:
                return SkConsistentChecksum::Compute(data, size);
            default:
                SkString message("fWhichAlgorithm has unknown value ");
                message.appendf("%d", fWhichAlgorithm);
                fReporter->reportFailed(message);
            }
            // we never get here
            return 0;
        }

        // Confirm that the checksum algorithm (specified by fWhichAlgorithm)
        // generates the same results if called twice over the same data.
        void TestChecksumSelfConsistency(size_t buf_size) {
            SkAutoMalloc storage(buf_size);
            uint32_t*    ptr = (uint32_t*)storage.get();
            char*        cptr = (char*)ptr;

            sk_bzero(ptr, buf_size);
            uint32_t prev = 0;

            // assert that as we change values (from 0 to non-zero) in
            // our buffer, we get a different value
            for (size_t i = 0; i < buf_size; ++i) {
                cptr[i] = (i & 0x7f) + 1; // need some non-zero value here

                // Try checksums of different-sized chunks, but always
                // 32-bit aligned and big enough to contain all the
                // nonzero bytes.
                size_t checksum_size = (((i/4)+1)*4);
                REPORTER_ASSERT(fReporter, checksum_size <= buf_size);

                uint32_t curr = ComputeChecksum(ptr, checksum_size);
                REPORTER_ASSERT(fReporter, prev != curr);
                uint32_t again = ComputeChecksum(ptr, checksum_size);
                REPORTER_ASSERT(fReporter, again == curr);
                prev = curr;
            }
        }

        // Return the checksum of a portion of this static test data
        // (8 bytes repeated twice): "1234567812345678"
        uint32_t GetTestDataChecksum(size_t offset, size_t len) {
            static char testbytes[] = "1234567812345678";
            uint32_t* ptr = reinterpret_cast<uint32_t*>(testbytes);
            return ComputeChecksum(ptr, len);
        }

        void RunTest() {
            // Test self-consistency of checksum algorithms.
            fWhichAlgorithm = kSkChecksum;
            REPORTER_ASSERT(fReporter,
                            GetTestDataChecksum(0, 8) ==
                            GetTestDataChecksum(8, 8));
            TestChecksumSelfConsistency(128);
            fWhichAlgorithm = kSkConsistentChecksum;
            REPORTER_ASSERT(fReporter,
                            GetTestDataChecksum(0, 8) ==
                            GetTestDataChecksum(8, 8));
            TestChecksumSelfConsistency(128);

            // Test checksum results that should be consistent across
            // versions and platforms.
            fWhichAlgorithm = kSkChecksum;
            REPORTER_ASSERT(fReporter, ComputeChecksum(NULL, 0) == 0);
            fWhichAlgorithm = kSkConsistentChecksum;
            REPORTER_ASSERT(fReporter, ComputeChecksum(NULL, 0) == 0);
            REPORTER_ASSERT(fReporter, GetTestDataChecksum(0, 8) == 0xa12fac2c);
            REPORTER_ASSERT(fReporter, GetTestDataChecksum(8, 8) == 0xa12fac2c);
            REPORTER_ASSERT(fReporter, GetTestDataChecksum(8, 4) == 0x34333231);
        }

        Reporter* fReporter;
        Algorithm fWhichAlgorithm;
    };

    static TestRegistry gReg(ChecksumTestClass::Factory);
}
<commit_msg>Add self-test that reveals SkChecksum weakness Review URL: https://codereview.appspot.com/6845064<commit_after>
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "Test.h"
#include "SkChecksum.h"
#include "SkConsistentChecksum.h"

namespace skiatest {
    class ChecksumTestClass : public Test {
    public:
        static Test* Factory(void*) {return SkNEW(ChecksumTestClass); }
    protected:
        virtual void onGetName(SkString* name) { name->set("Checksum"); }
        virtual void onRun(Reporter* reporter) {
            this->fReporter = reporter;
            RunTest();
        }
    private:
        enum Algorithm {
            kSkChecksum,
            kSkConsistentChecksum
        };

        // Call Compute(data, size) on the appropriate checksum algorithm,
        // depending on this->fWhichAlgorithm.
        uint32_t ComputeChecksum(uint32_t* data, size_t size) {
            // Our checksum algorithms require 32-bit aligned data.
            // If either of these tests fail, then the algorithm
            // doesn't have a chance.
            REPORTER_ASSERT_MESSAGE(fReporter,
                                    reinterpret_cast<uintptr_t>(data) % 4 == 0,
                                    "test data pointer is not 32-bit aligned");
            REPORTER_ASSERT_MESSAGE(fReporter, SkIsAlign4(size),
                                    "test data size is not 32-bit aligned");

            switch(fWhichAlgorithm) {
            case kSkChecksum:
                return SkChecksum::Compute(data, size);
            case kSkConsistentChecksum:
                return SkConsistentChecksum::Compute(data, size);
            default:
                SkString message("fWhichAlgorithm has unknown value ");
                message.appendf("%d", fWhichAlgorithm);
                fReporter->reportFailed(message);
            }
            // we never get here
            return 0;
        }

        // Confirm that the checksum algorithm (specified by fWhichAlgorithm)
        // generates the same results if called twice over the same data.
        void TestChecksumSelfConsistency(size_t buf_size) {
            SkAutoMalloc storage(buf_size);
            uint32_t*    ptr = (uint32_t*)storage.get();
            char*        cptr = (char*)ptr;

            sk_bzero(ptr, buf_size);
            uint32_t prev = 0;

            // assert that as we change values (from 0 to non-zero) in
            // our buffer, we get a different value
            for (size_t i = 0; i < buf_size; ++i) {
                cptr[i] = (i & 0x7f) + 1; // need some non-zero value here

                // Try checksums of different-sized chunks, but always
                // 32-bit aligned and big enough to contain all the
                // nonzero bytes.  (Remaining bytes will still be zero
                // from the initial sk_bzero() call.)
                size_t checksum_size = (((i/4)+1)*4);
                REPORTER_ASSERT(fReporter, checksum_size <= buf_size);

                uint32_t curr = ComputeChecksum(ptr, checksum_size);
                REPORTER_ASSERT(fReporter, prev != curr);
                uint32_t again = ComputeChecksum(ptr, checksum_size);
                REPORTER_ASSERT(fReporter, again == curr);
                prev = curr;
            }
        }

        // Return the checksum of a buffer of bytes 'len' long.
        // The pattern of values within the buffer will be consistent
        // for every call, based on 'seed'.
        uint32_t GetTestDataChecksum(size_t len, char seed=0) {
            SkAutoMalloc storage(len);
            uint32_t* start = (uint32_t *)storage.get();
            char* ptr = (char *)start;
            for (size_t i = 0; i < len; ++i) {
                *ptr++ = ((seed+i) & 0x7f);
            }
            uint32_t result = ComputeChecksum(start, len);
            return result;
        }

        void RunTest() {
            // Test self-consistency of checksum algorithms.
            fWhichAlgorithm = kSkChecksum;
            REPORTER_ASSERT(fReporter,
                            GetTestDataChecksum(8, 0) ==
                            GetTestDataChecksum(8, 0));
            REPORTER_ASSERT(fReporter,
                            GetTestDataChecksum(8, 0) !=
                            GetTestDataChecksum(8, 1));
            TestChecksumSelfConsistency(128);
            fWhichAlgorithm = kSkConsistentChecksum;
            REPORTER_ASSERT(fReporter,
                            GetTestDataChecksum(8, 0) ==
                            GetTestDataChecksum(8, 0));
            REPORTER_ASSERT(fReporter,
                            GetTestDataChecksum(8, 0) !=
                            GetTestDataChecksum(8, 1));
            TestChecksumSelfConsistency(128);

            // Test checksum results that should be consistent across
            // versions and platforms.
            fWhichAlgorithm = kSkChecksum;
            REPORTER_ASSERT(fReporter, ComputeChecksum(NULL, 0) == 0);
            fWhichAlgorithm = kSkConsistentChecksum;
            REPORTER_ASSERT(fReporter, ComputeChecksum(NULL, 0) == 0);
            REPORTER_ASSERT(fReporter, GetTestDataChecksum(4)  == 0x03020100);
            REPORTER_ASSERT(fReporter, GetTestDataChecksum(8)  == 0x07860485);

            // TODO: note the weakness exposed by these collisions...
            // We need to improve the SkConsistentChecksum algorithm
            // (and maybe SkChecksum too?)
            // We would prefer that these asserts FAIL!
            // Filed as https://code.google.com/p/skia/issues/detail?id=981
            // ('SkChecksum algorithm allows for way too many collisions')
            fWhichAlgorithm = kSkChecksum;
            REPORTER_ASSERT(fReporter,
                GetTestDataChecksum(128) == GetTestDataChecksum(256));
            REPORTER_ASSERT(fReporter,
                GetTestDataChecksum(132) == GetTestDataChecksum(260));
            fWhichAlgorithm = kSkConsistentChecksum;
            REPORTER_ASSERT(fReporter, GetTestDataChecksum(128) == 0);
            REPORTER_ASSERT(fReporter, GetTestDataChecksum(132) == 0x03020100);
            REPORTER_ASSERT(fReporter, GetTestDataChecksum(256) == 0);
            REPORTER_ASSERT(fReporter, GetTestDataChecksum(260) == 0x03020100);
        }

        Reporter* fReporter;
        Algorithm fWhichAlgorithm;
    };

    static TestRegistry gReg(ChecksumTestClass::Factory);
}
<|endoftext|>


<commit_before>#include "remote_logging_tests.hpp"
#include "xyz/openbmc_project/Common/error.hpp"

namespace phosphor
{
namespace logging
{
namespace test
{

using namespace sdbusplus::xyz::openbmc_project::Common::Error;

TEST_F(TestRemoteLogging, testGoodAddress)
{
    config->address("1.1.1.1");
    EXPECT_EQ(config->address(), "1.1.1.1");
}

TEST_F(TestRemoteLogging, testBadAddress)
{
    EXPECT_THROW(config->address("not_an_IP"), InvalidArgument);
}

} // namespace test
} // namespace logging
} // namespace phosphor
<commit_msg>invalid-address: ensure bad path is invalid<commit_after>#include "remote_logging_tests.hpp"
#include "xyz/openbmc_project/Common/error.hpp"

namespace phosphor
{
namespace logging
{
namespace test
{

using namespace sdbusplus::xyz::openbmc_project::Common::Error;

TEST_F(TestRemoteLogging, testGoodAddress)
{
    config->address("1.1.1.1");
    EXPECT_EQ(config->address(), "1.1.1.1");
}

TEST_F(TestRemoteLogging, testBadAddress)
{
    EXPECT_THROW(config->address("this is not_an_IP!"), InvalidArgument);
}

} // namespace test
} // namespace logging
} // namespace phosphor
<|endoftext|>