<commit_before>/*
 * This is part of the fl library, a C++ Bayesian filtering library
 * (https://github.com/filtering-library)
 *
 * Copyright (c) 2015 Max Planck Society,
 * 				 Autonomous Motion Department,
 * 			     Institute for Intelligent Systems
 *
 * This Source Code Form is subject to the terms of the MIT License (MIT).
 * A copy of the license can be found in the LICENSE file distributed with this
 * source code.
 */

/**
 * \file robust_feature_obsrv_model.hpp
 * \date August 2015
 * \author Jan Issac (jan.issac@gmail.com)
 */

#pragma once

#include <fl/util/meta.hpp>
#include <fl/util/traits.hpp>
#include <fl/util/types.hpp>
#include <fl/util/descriptor.hpp>
#include <fl/distribution/gaussian.hpp>
#include <fl/model/observation/interface/observation_density.hpp>
#include <fl/model/observation/interface/observation_function.hpp>

namespace fl
{

namespace internal
{

enum RobustFeatureDimension { RobustFeatureDimExt = 2 };

}

/**
 * \ingroup observation_models
 *
 * \brief Represents an observation function or model which takes an arbitrary
 *        observation model (one that implements an ObservationFunction & a
 *        an ObservationDensity) as an argument and maps it into a feature space
 *        used by the RobustGaussianFilter.
 */
template <typename ObsrvModel>
class RobustFeatureObsrvModel
    : public ObservationFunction<
                 /* Obsrv type of the size SizeOf<ObsrvModel::Obsrv> + 2 */
                 typename VariateOfSize<
                     JoinSizes<
                         SizeOf<typename ObsrvModel::Obsrv>::Value,
                         internal::RobustFeatureDimExt
                     >::Value
                 >::Type,
                 typename ObsrvModel::State,
                 typename ObsrvModel::Noise>,
      public Descriptor

{
private:
    typedef RobustFeatureObsrvModel<ObsrvModel> This;

public:
    typedef ObsrvModel EmbeddedObsrvModel;

    /**
     * \brief \a InputObsrv type which is the same as
     *        ObsrvModel::Obsrv. \a InputObsrv is mapped into the feature space.
     *        The resulting type is \a Obsrv.
     */
    typedef typename ObsrvModel::Obsrv InputObsrv;

    /**
     * \brief \a Obsrv (\f$y_t\f$) type which is a variate of the size
     *        SizeOf<InputObsrv> + 2. \a Obsrv reside in the feature space.
     */
    typedef typename VariateOfSize<
                         JoinSizes<
                             SizeOf<typename ObsrvModel::Obsrv>::Value,
                             internal::RobustFeatureDimExt
                         >::Value
                     >::Type Obsrv;

    /**
     * \brief \a State (\f$x_t\f$) type which is the same as ObsrvModel::State
     */
    typedef typename ObsrvModel::State State;

    /**
     * \brief \a Noise (\f$x_t\f$) type which is the same as ObsrvModel::Noise
     */
    typedef typename ObsrvModel::Noise Noise;

public:
    /**
     * \brief Constructs a robust feature observation model for the robust
     *        gaussian filter
     *
     * \param obsrv_model   Reference to the source observation model
     *
     * \note This model takes only a reference of to an existing lvalue of the
     *       source model
     */
    explicit RobustFeatureObsrvModel(ObsrvModel& obsrv_model)
        : obsrv_model_(obsrv_model),
          body_gaussian_(obsrv_model.obsrv_dimension())
    { }

    /**
     * \brief Overridable default destructor
     */
    virtual ~RobustFeatureObsrvModel() noexcept { }

    /**
     * \brief observation Returns a feature mapped observation
     */
    Obsrv observation(const State& state, const Noise& noise) const override
    {
        auto input_obsrv = obsrv_model_.observation(state, noise);
        Obsrv y = feature_obsrv(input_obsrv);
        return y; // RVO
    }

    /**
     * \brief Computes the robust feature given an input feature fron the
     *        source observation model
     */
    virtual Obsrv feature_obsrv(const InputObsrv& input_obsrv) const
    {
        auto y = Obsrv(obsrv_dimension());

        //! \todo BG changes
        if(!std::isfinite(input_obsrv(0)))
        {
            for(int i = 0; i < y.size(); i++)
            {
                y(i) = std::numeric_limits<Real>::infinity();
            }
            return y;
        }

        auto weight = obsrv_model_.tail_weight();
        auto prob_y = body_gaussian_.probability(input_obsrv);
        auto prob_tail = obsrv_model_
                            .tail_model()
                            .probability(input_obsrv, mean_state_);

        auto normalizer = 1.0 / ((1.0 - weight) * prob_y + weight * prob_tail);

        if(weight == 0)
        {
            y(0) = 0.0;
            if (internal::RobustFeatureDimExt == 2) y(1) = 1.0;
            y.bottomRows(obsrv_model_.obsrv_dimension()) = input_obsrv;
        }
        else if( !std::isfinite(1.0 / (weight * prob_tail)) )
        {
            std::cout << "prob_tail is too small: " << prob_tail
                      << "    weight: " << weight
                      << "    input_obsrv: " << input_obsrv.transpose()
                      << "    normalizer: " << normalizer
                      << std::endl;
            exit(-1);
        }
        else if(std::isfinite(normalizer))
        {
            y(0) = weight * prob_tail;
            if (internal::RobustFeatureDimExt == 2) y(1) =
                                                    (1.0 - weight) *  prob_y;
            y.bottomRows(obsrv_model_.obsrv_dimension()) =
                                        (1.0 - weight) * prob_y * input_obsrv;
            y *= normalizer;
        }
        else // if the normalizer is not finite, we assume that the
        {
            std::cout << "normalizer in robust feature is not finite "
                      << "    weight: " << weight
                      << "    input_obsrv: " << input_obsrv.transpose()
                      << "    normalizer: " << normalizer
                      << std::endl;
            exit(-1);

        }

        return y;
    }

    /**
     * \brief Sets the feature function \a mean_state;
     * \param mean_state        \f$ \mu_x \f$
     *
     * \todo PAPER REF
     */
    virtual void mean_state(const State& mean_state)
    {
        mean_state_ = mean_state;
    }

    /**
     * \brief Sets the feature function body moments
     * \param body_gaussian     \f${\cal N}(y_t\mid \mu_{y}, \Sigma_{yy})\f$
     *
     * \todo PAPER REF
     */
    virtual void body_moments(
        const typename FirstMomentOf<InputObsrv>::Type& mean_obsrv,
        const typename SecondMomentOf<InputObsrv>::Type& cov_obsrv)
    {
        body_gaussian_.mean(mean_obsrv);
        body_gaussian_.covariance(cov_obsrv);
    }

    /**
     * \brief Returns the dimension of the \a Obsrv which is dim(\a Obsrv) + 2
     */
    int obsrv_dimension() const override
    {
        return obsrv_model_.obsrv_dimension() + internal::RobustFeatureDimExt;
    }

    int noise_dimension() const override
    {
        return obsrv_model_.noise_dimension();
    }

    int state_dimension() const override
    {
        return obsrv_model_.state_dimension();
    }

    ObsrvModel& embedded_obsrv_model()
    {
        return obsrv_model_;
    }

    const ObsrvModel& embedded_obsrv_model() const
    {
        return obsrv_model_;
    }

    virtual int id() const { return obsrv_model_.id(); }

    virtual void id(int new_id) { obsrv_model_.id(new_id); }

    virtual std::string name() const
    {
        return "RobustFeatureObsrvModel<"
                + this->list_arguments(embedded_obsrv_model().name())
                + ">";
    }

    virtual std::string description() const
    {
        return "Robust feature observation model with "
                + this->list_descriptions(embedded_obsrv_model().description());
    }

public:
    /** \cond internal */

    /**
     * \brief Reference to the ource observation model
     */
    ObsrvModel& obsrv_model_;

    /**
     * \brief \f${\cal N}(y_t\mid \mu_{y}, \Sigma_{yy})\f$
     */
    Gaussian<InputObsrv> body_gaussian_;

    /**
     * \brief \f$\mu_x\f$
     */
    State mean_state_;

    /* \endcond */
};

}

<commit_msg>Added more details on error<commit_after>/*
 * This is part of the fl library, a C++ Bayesian filtering library
 * (https://github.com/filtering-library)
 *
 * Copyright (c) 2015 Max Planck Society,
 * 				 Autonomous Motion Department,
 * 			     Institute for Intelligent Systems
 *
 * This Source Code Form is subject to the terms of the MIT License (MIT).
 * A copy of the license can be found in the LICENSE file distributed with this
 * source code.
 */

/**
 * \file robust_feature_obsrv_model.hpp
 * \date August 2015
 * \author Jan Issac (jan.issac@gmail.com)
 */

#pragma once

#include <fl/util/meta.hpp>
#include <fl/util/traits.hpp>
#include <fl/util/types.hpp>
#include <fl/util/descriptor.hpp>
#include <fl/distribution/gaussian.hpp>
#include <fl/model/observation/interface/observation_density.hpp>
#include <fl/model/observation/interface/observation_function.hpp>

namespace fl
{

namespace internal
{

enum RobustFeatureDimension { RobustFeatureDimExt = 2 };

}

/**
 * \ingroup observation_models
 *
 * \brief Represents an observation function or model which takes an arbitrary
 *        observation model (one that implements an ObservationFunction & a
 *        an ObservationDensity) as an argument and maps it into a feature space
 *        used by the RobustGaussianFilter.
 */
template <typename ObsrvModel>
class RobustFeatureObsrvModel
    : public ObservationFunction<
                 /* Obsrv type of the size SizeOf<ObsrvModel::Obsrv> + 2 */
                 typename VariateOfSize<
                     JoinSizes<
                         SizeOf<typename ObsrvModel::Obsrv>::Value,
                         internal::RobustFeatureDimExt
                     >::Value
                 >::Type,
                 typename ObsrvModel::State,
                 typename ObsrvModel::Noise>,
      public Descriptor

{
private:
    typedef RobustFeatureObsrvModel<ObsrvModel> This;

public:
    typedef ObsrvModel EmbeddedObsrvModel;

    /**
     * \brief \a InputObsrv type which is the same as
     *        ObsrvModel::Obsrv. \a InputObsrv is mapped into the feature space.
     *        The resulting type is \a Obsrv.
     */
    typedef typename ObsrvModel::Obsrv InputObsrv;

    /**
     * \brief \a Obsrv (\f$y_t\f$) type which is a variate of the size
     *        SizeOf<InputObsrv> + 2. \a Obsrv reside in the feature space.
     */
    typedef typename VariateOfSize<
                         JoinSizes<
                             SizeOf<typename ObsrvModel::Obsrv>::Value,
                             internal::RobustFeatureDimExt
                         >::Value
                     >::Type Obsrv;

    /**
     * \brief \a State (\f$x_t\f$) type which is the same as ObsrvModel::State
     */
    typedef typename ObsrvModel::State State;

    /**
     * \brief \a Noise (\f$x_t\f$) type which is the same as ObsrvModel::Noise
     */
    typedef typename ObsrvModel::Noise Noise;

public:
    /**
     * \brief Constructs a robust feature observation model for the robust
     *        gaussian filter
     *
     * \param obsrv_model   Reference to the source observation model
     *
     * \note This model takes only a reference of to an existing lvalue of the
     *       source model
     */
    explicit RobustFeatureObsrvModel(ObsrvModel& obsrv_model)
        : obsrv_model_(obsrv_model),
          body_gaussian_(obsrv_model.obsrv_dimension())
    { }

    /**
     * \brief Overridable default destructor
     */
    virtual ~RobustFeatureObsrvModel() noexcept { }

    /**
     * \brief observation Returns a feature mapped observation
     */
    Obsrv observation(const State& state, const Noise& noise) const override
    {
        auto input_obsrv = obsrv_model_.observation(state, noise);
        Obsrv y = feature_obsrv(input_obsrv);
        return y; // RVO
    }

    /**
     * \brief Computes the robust feature given an input feature fron the
     *        source observation model
     */
    virtual Obsrv feature_obsrv(const InputObsrv& input_obsrv) const
    {
        auto y = Obsrv(obsrv_dimension());

        //! \todo BG changes
        if(!std::isfinite(input_obsrv(0)))
        {
            for(int i = 0; i < y.size(); i++)
            {
                y(i) = std::numeric_limits<Real>::infinity();
            }
            return y;
        }

        auto weight = obsrv_model_.tail_weight();
        auto prob_y = body_gaussian_.probability(input_obsrv);
        auto prob_tail = obsrv_model_
                            .tail_model()
                            .probability(input_obsrv, mean_state_);

        auto normalizer = 1.0 / ((1.0 - weight) * prob_y + weight * prob_tail);

        if(weight == 0)
        {
            y(0) = 0.0;
            if (internal::RobustFeatureDimExt == 2) y(1) = 1.0;
            y.bottomRows(obsrv_model_.obsrv_dimension()) = input_obsrv;
        }
        else if( !std::isfinite(1.0 / (weight * prob_tail)) )
        {
            std::cout << "prob_tail is too small: " << prob_tail
                      << "    weight: " << weight
                      << "    input_obsrv: " << input_obsrv.transpose()
                      << "    normalizer: " << normalizer
                      << std::endl;
            exit(-1);
        }
        else if(std::isfinite(normalizer))
        {
            y(0) = weight * prob_tail;
            if (internal::RobustFeatureDimExt == 2) y(1) =
                                                    (1.0 - weight) *  prob_y;
            y.bottomRows(obsrv_model_.obsrv_dimension()) =
                                        (1.0 - weight) * prob_y * input_obsrv;
            y *= normalizer;
        }
        else // if the normalizer is not finite, we assume that the
        {
            std::cout << "normalizer in robust feature is not finite "
                      << "    weight: " << weight
                      << "    prob_y: " << prob_y
                      << "    body_mean " <<   body_gaussian_.mean()
                      << "    body_cov " <<   body_gaussian_.covariance()
                      << "    prob_y: " << prob_y
                      << "    input_obsrv: " << input_obsrv.transpose()
                      << "    normalizer: " << normalizer
                      << std::endl;
            exit(-1);

        }

        return y;
    }

    /**
     * \brief Sets the feature function \a mean_state;
     * \param mean_state        \f$ \mu_x \f$
     *
     * \todo PAPER REF
     */
    virtual void mean_state(const State& mean_state)
    {
        mean_state_ = mean_state;
    }

    /**
     * \brief Sets the feature function body moments
     * \param body_gaussian     \f${\cal N}(y_t\mid \mu_{y}, \Sigma_{yy})\f$
     *
     * \todo PAPER REF
     */
    virtual void body_moments(
        const typename FirstMomentOf<InputObsrv>::Type& mean_obsrv,
        const typename SecondMomentOf<InputObsrv>::Type& cov_obsrv)
    {
        body_gaussian_.mean(mean_obsrv);
        body_gaussian_.covariance(cov_obsrv);
    }

    /**
     * \brief Returns the dimension of the \a Obsrv which is dim(\a Obsrv) + 2
     */
    int obsrv_dimension() const override
    {
        return obsrv_model_.obsrv_dimension() + internal::RobustFeatureDimExt;
    }

    int noise_dimension() const override
    {
        return obsrv_model_.noise_dimension();
    }

    int state_dimension() const override
    {
        return obsrv_model_.state_dimension();
    }

    ObsrvModel& embedded_obsrv_model()
    {
        return obsrv_model_;
    }

    const ObsrvModel& embedded_obsrv_model() const
    {
        return obsrv_model_;
    }

    virtual int id() const { return obsrv_model_.id(); }

    virtual void id(int new_id) { obsrv_model_.id(new_id); }

    virtual std::string name() const
    {
        return "RobustFeatureObsrvModel<"
                + this->list_arguments(embedded_obsrv_model().name())
                + ">";
    }

    virtual std::string description() const
    {
        return "Robust feature observation model with "
                + this->list_descriptions(embedded_obsrv_model().description());
    }

public:
    /** \cond internal */

    /**
     * \brief Reference to the ource observation model
     */
    ObsrvModel& obsrv_model_;

    /**
     * \brief \f${\cal N}(y_t\mid \mu_{y}, \Sigma_{yy})\f$
     */
    Gaussian<InputObsrv> body_gaussian_;

    /**
     * \brief \f$\mu_x\f$
     */
    State mean_state_;

    /* \endcond */
};

}

<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Tests for the top plugins to catch regressions in our plugin host code, as
// well as in the out of process code.  Currently this tests:
//  Flash
//  Real
//  QuickTime
//  Windows Media Player
//    -this includes both WMP plugins.  npdsplay.dll is the older one that
//     comes with XP.  np-mswmp.dll can be downloaded from Microsoft and
//     needs SP2 or Vista.

#include "build/build_config.h"

#if defined(OS_WIN)
#include <windows.h>
#include <shellapi.h>
#include <shlobj.h>
#include <comutil.h>
#endif

#include <stdlib.h>
#include <string.h>
#include <memory.h>

#include <string>

#include "base/file_path.h"
#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "chrome/browser/net/url_request_mock_http_job.h"
#include "chrome/browser/plugin_download_helper.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/capturing_net_log.h"
#include "net/base/cert_verifier.h"
#include "net/base/host_resolver.h"
#include "net/base/net_util.h"
#include "net/base/ssl_config_service_defaults.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_cache.h"
#include "net/http/http_network_layer.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_status.h"
#include "third_party/npapi/bindings/npapi.h"
#include "webkit/plugins/npapi/plugin_constants_win.h"
#include "webkit/plugins/npapi/plugin_list.h"
#include "webkit/plugins/plugin_switches.h"

#if defined(OS_WIN)
#include "base/win/registry.h"
#endif

class PluginTest : public UITest {
 public:
  // Generate the URL for testing a particular test.
  // HTML for the tests is all located in test_directory\plugin\<testcase>
  // Set |mock_http| to true to use mock HTTP server.
  static GURL GetTestUrl(const std::string &test_case, bool mock_http) {
    static const FilePath::CharType kPluginPath[] = FILE_PATH_LITERAL("plugin");
    if (mock_http) {
      FilePath plugin_path = FilePath(kPluginPath).AppendASCII(test_case);
      return URLRequestMockHTTPJob::GetMockUrl(plugin_path);
    }

    FilePath path;
    PathService::Get(chrome::DIR_TEST_DATA, &path);
    path = path.Append(kPluginPath).AppendASCII(test_case);
    return net::FilePathToFileURL(path);
  }

 protected:
#if defined(OS_WIN)
  virtual void SetUp() {
    const testing::TestInfo* const test_info =
        testing::UnitTest::GetInstance()->current_test_info();
    if (strcmp(test_info->name(), "MediaPlayerNew") == 0) {
      // The installer adds our process names to the registry key below.  Since
      // the installer might not have run on this machine, add it manually.
      base::win::RegKey regkey;
      if (regkey.Open(HKEY_LOCAL_MACHINE,
                      L"Software\\Microsoft\\MediaPlayer\\ShimInclusionList",
                      KEY_WRITE)) {
        regkey.CreateKey(L"CHROME.EXE", KEY_READ);
      }
    } else if (strcmp(test_info->name(), "MediaPlayerOld") == 0) {
      // When testing the old WMP plugin, we need to force Chrome to not load
      // the new plugin.
      launch_arguments_.AppendSwitch(switches::kUseOldWMPPlugin);
    } else if (strcmp(test_info->name(), "FlashSecurity") == 0) {
      launch_arguments_.AppendSwitchASCII(switches::kTestSandbox,
                                          "security_tests.dll");
    }

    UITest::SetUp();
  }
#endif  // defined(OS_WIN)

  void TestPlugin(const std::string& test_case,
                  int timeout,
                  bool mock_http) {
    GURL url = GetTestUrl(test_case, mock_http);
    NavigateToURL(url);
    WaitForFinish(timeout, mock_http);
  }

  // Waits for the test case to finish.
  void WaitForFinish(const int wait_time, bool mock_http) {
    static const char kTestCompleteCookie[] = "status";
    static const char kTestCompleteSuccess[] = "OK";

    GURL url = GetTestUrl("done", mock_http);
    scoped_refptr<TabProxy> tab(GetActiveTab());

    const std::string result =
        WaitUntilCookieNonEmpty(tab, url, kTestCompleteCookie, wait_time);
    ASSERT_EQ(kTestCompleteSuccess, result);
  }
};

TEST_F(PluginTest, Flash) {
  // Note: This does not work with the npwrapper on 64-bit Linux. Install the
  // native 64-bit Flash to run the test.
  // TODO(thestig) Update this list if we decide to only test against internal
  // Flash plugin in the future?
  std::string kFlashQuery =
#if defined(OS_WIN)
      "npswf32.dll"
#elif defined(OS_MACOSX)
      "Flash Player.plugin"
#elif defined(OS_POSIX)
      "libflashplayer.so"
#endif
      ;
  TestPlugin("flash.html?" + kFlashQuery, action_max_timeout_ms(), false);
}

class ClickToPlayPluginTest : public PluginTest {
 public:
  ClickToPlayPluginTest() {
    dom_automation_enabled_ = true;
  }
};

TEST_F(ClickToPlayPluginTest, Flash) {
  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());
  ASSERT_TRUE(browser->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS,
                                                CONTENT_SETTING_BLOCK));

  GURL url = GetTestUrl("flash-clicktoplay.html", true);
  NavigateToURL(url);

  scoped_refptr<TabProxy> tab(browser->GetTab(0));
  ASSERT_TRUE(tab.get());

  ASSERT_TRUE(tab->LoadBlockedPlugins());

  WaitForFinish(action_max_timeout_ms(), true);
}

TEST_F(ClickToPlayPluginTest, FlashDocument) {
  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());
  ASSERT_TRUE(browser->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS,
                                                CONTENT_SETTING_BLOCK));

  scoped_refptr<TabProxy> tab(browser->GetTab(0));
  ASSERT_TRUE(tab.get());
  GURL url = GetTestUrl("js-invoker.swf?callback=done", true);
  NavigateToURL(url);

  // Inject the callback function into the HTML page generated by the browser.
  ASSERT_TRUE(tab->ExecuteJavaScript("window.done = function() {"
                                     "  window.location = \"done.html\";"
                                     "}"));

  ASSERT_TRUE(tab->LoadBlockedPlugins());

  WaitForFinish(action_max_timeout_ms(), true);
}

#if defined(OS_WIN)
// Windows only test
TEST_F(PluginTest, DISABLED_FlashSecurity) {
  TestPlugin("flash.html", action_max_timeout_ms(), false);
}
#endif  // defined(OS_WIN)

#if defined(OS_WIN)
// TODO(port) Port the following tests to platforms that have the required
// plugins.
// Flaky: http://crbug.com/55915
TEST_F(PluginTest, FLAKY_Quicktime) {
  TestPlugin("quicktime.html", action_max_timeout_ms(), false);
}

// Disabled on Release bots - http://crbug.com/44662
#if defined(NDEBUG)
#define MediaPlayerNew DISABLED_MediaPlayerNew
#endif
TEST_F(PluginTest, MediaPlayerNew) {
  TestPlugin("wmp_new.html", action_max_timeout_ms(), false);
}

// http://crbug.com/4809
TEST_F(PluginTest, DISABLED_MediaPlayerOld) {
  TestPlugin("wmp_old.html", action_max_timeout_ms(), false);
}

#if defined(NDEBUG)
#define Real DISABLED_Real
#endif
// Disabled on Release bots - http://crbug.com/44673
TEST_F(PluginTest, Real) {
  TestPlugin("real.html", action_max_timeout_ms(), false);
}

TEST_F(PluginTest, FlashOctetStream) {
  TestPlugin("flash-octet-stream.html", action_max_timeout_ms(), false);
}

#if defined(OS_WIN)
// http://crbug.com/53926
TEST_F(PluginTest, FLAKY_FlashLayoutWhilePainting) {
#else
TEST_F(PluginTest, FlashLayoutWhilePainting) {
#endif
  TestPlugin("flash-layout-while-painting.html", action_max_timeout_ms(), true);
}

// http://crbug.com/8690
TEST_F(PluginTest, DISABLED_Java) {
  TestPlugin("Java.html", action_max_timeout_ms(), false);
}

TEST_F(PluginTest, Silverlight) {
  TestPlugin("silverlight.html", action_max_timeout_ms(), false);
}

// This class provides functionality to test the plugin installer download
// file functionality.
class PluginInstallerDownloadTest
    : public PluginDownloadUrlHelper::DownloadDelegate,
      public testing::Test {
 public:
  // This class provides HTTP request context information for the downloads.
  class UploadRequestContext : public URLRequestContext {
   public:
    UploadRequestContext() {
      Initialize();
    }

    ~UploadRequestContext() {
      DVLOG(1) << __FUNCTION__;
      delete http_transaction_factory_;
      delete http_auth_handler_factory_;
      delete cert_verifier_;
      delete host_resolver_;
    }

    void Initialize() {
      host_resolver_ =
          net::CreateSystemHostResolver(net::HostResolver::kDefaultParallelism,
                                        NULL, NULL);
      cert_verifier_ = new net::CertVerifier;
      net::ProxyConfigService* proxy_config_service =
          net::ProxyService::CreateSystemProxyConfigService(NULL, NULL);
      DCHECK(proxy_config_service);

      const size_t kNetLogBound = 50u;
      net_log_.reset(new net::CapturingNetLog(kNetLogBound));

      proxy_service_ = net::ProxyService::CreateUsingSystemProxyResolver(
          proxy_config_service, 0, net_log_.get());
      DCHECK(proxy_service_);

      ssl_config_service_ = new net::SSLConfigServiceDefaults;
      http_auth_handler_factory_ = net::HttpAuthHandlerFactory::CreateDefault(
          host_resolver_);
      http_transaction_factory_ = new net::HttpCache(
          net::HttpNetworkLayer::CreateFactory(host_resolver_,
                                               cert_verifier_,
                                               NULL /* dnsrr_resolver */,
                                               NULL /* dns_cert_checker */,
                                               NULL /* ssl_host_info_factory */,
                                               proxy_service_,
                                               ssl_config_service_,
                                               http_auth_handler_factory_,
                                               network_delegate_,
                                               NULL),
          net::HttpCache::DefaultBackend::InMemory(0));
    }

   private:
    scoped_ptr<net::NetLog> net_log_;
    scoped_ptr<net::URLSecurityManager> url_security_manager_;
  };

  PluginInstallerDownloadTest()
      : success_(false),
        download_helper_(NULL) {}
  ~PluginInstallerDownloadTest() {}

  void Start() {
    initial_download_path_ = PluginTest::GetTestUrl("flash.html", false);
    download_helper_ = new PluginDownloadUrlHelper(
        initial_download_path_.spec(), base::GetCurrentProcId(), NULL,
        static_cast<PluginDownloadUrlHelper::DownloadDelegate*>(this));
    download_helper_->InitiateDownload(new UploadRequestContext);

    MessageLoop::current()->PostDelayedTask(
        FROM_HERE, new MessageLoop::QuitTask,
        TestTimeouts::action_max_timeout_ms());
  }

  virtual void OnDownloadCompleted(const FilePath& download_path,
                                   bool success) {
    success_ = success;
    final_download_path_ = download_path;
    MessageLoop::current()->Quit();
    download_helper_ = NULL;
  }

  FilePath final_download_path() const {
    return final_download_path_;
  }

  FilePath initial_download_path() const {
    return final_download_path_;
  }

  bool success() const {
    return success_;
  }

 private:
  FilePath final_download_path_;
  PluginDownloadUrlHelper* download_helper_;
  bool success_;
  GURL initial_download_path_;
};

// This test validates that the plugin downloader downloads the specified file
// to a temporary path with the same file name.
TEST_F(PluginInstallerDownloadTest, PluginInstallerDownloadPathTest) {
  MessageLoop loop(MessageLoop::TYPE_IO);
  Start();
  loop.Run();

  EXPECT_TRUE(success());
  EXPECT_TRUE(initial_download_path().BaseName().value() ==
              final_download_path().BaseName().value());
}
#endif  // defined(OS_WIN)
<commit_msg>Disabling the MediaPlayerNew plugin test as it seems to fail consistently causing the XP Perf dbg builder to turn red.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Tests for the top plugins to catch regressions in our plugin host code, as
// well as in the out of process code.  Currently this tests:
//  Flash
//  Real
//  QuickTime
//  Windows Media Player
//    -this includes both WMP plugins.  npdsplay.dll is the older one that
//     comes with XP.  np-mswmp.dll can be downloaded from Microsoft and
//     needs SP2 or Vista.

#include "build/build_config.h"

#if defined(OS_WIN)
#include <windows.h>
#include <shellapi.h>
#include <shlobj.h>
#include <comutil.h>
#endif

#include <stdlib.h>
#include <string.h>
#include <memory.h>

#include <string>

#include "base/file_path.h"
#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "chrome/browser/net/url_request_mock_http_job.h"
#include "chrome/browser/plugin_download_helper.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/capturing_net_log.h"
#include "net/base/cert_verifier.h"
#include "net/base/host_resolver.h"
#include "net/base/net_util.h"
#include "net/base/ssl_config_service_defaults.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_cache.h"
#include "net/http/http_network_layer.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_status.h"
#include "third_party/npapi/bindings/npapi.h"
#include "webkit/plugins/npapi/plugin_constants_win.h"
#include "webkit/plugins/npapi/plugin_list.h"
#include "webkit/plugins/plugin_switches.h"

#if defined(OS_WIN)
#include "base/win/registry.h"
#endif

class PluginTest : public UITest {
 public:
  // Generate the URL for testing a particular test.
  // HTML for the tests is all located in test_directory\plugin\<testcase>
  // Set |mock_http| to true to use mock HTTP server.
  static GURL GetTestUrl(const std::string &test_case, bool mock_http) {
    static const FilePath::CharType kPluginPath[] = FILE_PATH_LITERAL("plugin");
    if (mock_http) {
      FilePath plugin_path = FilePath(kPluginPath).AppendASCII(test_case);
      return URLRequestMockHTTPJob::GetMockUrl(plugin_path);
    }

    FilePath path;
    PathService::Get(chrome::DIR_TEST_DATA, &path);
    path = path.Append(kPluginPath).AppendASCII(test_case);
    return net::FilePathToFileURL(path);
  }

 protected:
#if defined(OS_WIN)
  virtual void SetUp() {
    const testing::TestInfo* const test_info =
        testing::UnitTest::GetInstance()->current_test_info();
    if (strcmp(test_info->name(), "MediaPlayerNew") == 0) {
      // The installer adds our process names to the registry key below.  Since
      // the installer might not have run on this machine, add it manually.
      base::win::RegKey regkey;
      if (regkey.Open(HKEY_LOCAL_MACHINE,
                      L"Software\\Microsoft\\MediaPlayer\\ShimInclusionList",
                      KEY_WRITE)) {
        regkey.CreateKey(L"CHROME.EXE", KEY_READ);
      }
    } else if (strcmp(test_info->name(), "MediaPlayerOld") == 0) {
      // When testing the old WMP plugin, we need to force Chrome to not load
      // the new plugin.
      launch_arguments_.AppendSwitch(switches::kUseOldWMPPlugin);
    } else if (strcmp(test_info->name(), "FlashSecurity") == 0) {
      launch_arguments_.AppendSwitchASCII(switches::kTestSandbox,
                                          "security_tests.dll");
    }

    UITest::SetUp();
  }
#endif  // defined(OS_WIN)

  void TestPlugin(const std::string& test_case,
                  int timeout,
                  bool mock_http) {
    GURL url = GetTestUrl(test_case, mock_http);
    NavigateToURL(url);
    WaitForFinish(timeout, mock_http);
  }

  // Waits for the test case to finish.
  void WaitForFinish(const int wait_time, bool mock_http) {
    static const char kTestCompleteCookie[] = "status";
    static const char kTestCompleteSuccess[] = "OK";

    GURL url = GetTestUrl("done", mock_http);
    scoped_refptr<TabProxy> tab(GetActiveTab());

    const std::string result =
        WaitUntilCookieNonEmpty(tab, url, kTestCompleteCookie, wait_time);
    ASSERT_EQ(kTestCompleteSuccess, result);
  }
};

TEST_F(PluginTest, Flash) {
  // Note: This does not work with the npwrapper on 64-bit Linux. Install the
  // native 64-bit Flash to run the test.
  // TODO(thestig) Update this list if we decide to only test against internal
  // Flash plugin in the future?
  std::string kFlashQuery =
#if defined(OS_WIN)
      "npswf32.dll"
#elif defined(OS_MACOSX)
      "Flash Player.plugin"
#elif defined(OS_POSIX)
      "libflashplayer.so"
#endif
      ;
  TestPlugin("flash.html?" + kFlashQuery, action_max_timeout_ms(), false);
}

class ClickToPlayPluginTest : public PluginTest {
 public:
  ClickToPlayPluginTest() {
    dom_automation_enabled_ = true;
  }
};

TEST_F(ClickToPlayPluginTest, Flash) {
  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());
  ASSERT_TRUE(browser->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS,
                                                CONTENT_SETTING_BLOCK));

  GURL url = GetTestUrl("flash-clicktoplay.html", true);
  NavigateToURL(url);

  scoped_refptr<TabProxy> tab(browser->GetTab(0));
  ASSERT_TRUE(tab.get());

  ASSERT_TRUE(tab->LoadBlockedPlugins());

  WaitForFinish(action_max_timeout_ms(), true);
}

TEST_F(ClickToPlayPluginTest, FlashDocument) {
  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());
  ASSERT_TRUE(browser->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS,
                                                CONTENT_SETTING_BLOCK));

  scoped_refptr<TabProxy> tab(browser->GetTab(0));
  ASSERT_TRUE(tab.get());
  GURL url = GetTestUrl("js-invoker.swf?callback=done", true);
  NavigateToURL(url);

  // Inject the callback function into the HTML page generated by the browser.
  ASSERT_TRUE(tab->ExecuteJavaScript("window.done = function() {"
                                     "  window.location = \"done.html\";"
                                     "}"));

  ASSERT_TRUE(tab->LoadBlockedPlugins());

  WaitForFinish(action_max_timeout_ms(), true);
}

#if defined(OS_WIN)
// Windows only test
TEST_F(PluginTest, DISABLED_FlashSecurity) {
  TestPlugin("flash.html", action_max_timeout_ms(), false);
}
#endif  // defined(OS_WIN)

#if defined(OS_WIN)
// TODO(port) Port the following tests to platforms that have the required
// plugins.
// Flaky: http://crbug.com/55915
TEST_F(PluginTest, FLAKY_Quicktime) {
  TestPlugin("quicktime.html", action_max_timeout_ms(), false);
}

// Disabled - http://crbug.com/44662
TEST_F(PluginTest, DISABLED_MediaPlayerNew) {
  TestPlugin("wmp_new.html", action_max_timeout_ms(), false);
}

// http://crbug.com/4809
TEST_F(PluginTest, DISABLED_MediaPlayerOld) {
  TestPlugin("wmp_old.html", action_max_timeout_ms(), false);
}

#if defined(NDEBUG)
#define Real DISABLED_Real
#endif
// Disabled on Release bots - http://crbug.com/44673
TEST_F(PluginTest, Real) {
  TestPlugin("real.html", action_max_timeout_ms(), false);
}

TEST_F(PluginTest, FlashOctetStream) {
  TestPlugin("flash-octet-stream.html", action_max_timeout_ms(), false);
}

#if defined(OS_WIN)
// http://crbug.com/53926
TEST_F(PluginTest, FLAKY_FlashLayoutWhilePainting) {
#else
TEST_F(PluginTest, FlashLayoutWhilePainting) {
#endif
  TestPlugin("flash-layout-while-painting.html", action_max_timeout_ms(), true);
}

// http://crbug.com/8690
TEST_F(PluginTest, DISABLED_Java) {
  TestPlugin("Java.html", action_max_timeout_ms(), false);
}

TEST_F(PluginTest, Silverlight) {
  TestPlugin("silverlight.html", action_max_timeout_ms(), false);
}

// This class provides functionality to test the plugin installer download
// file functionality.
class PluginInstallerDownloadTest
    : public PluginDownloadUrlHelper::DownloadDelegate,
      public testing::Test {
 public:
  // This class provides HTTP request context information for the downloads.
  class UploadRequestContext : public URLRequestContext {
   public:
    UploadRequestContext() {
      Initialize();
    }

    ~UploadRequestContext() {
      DVLOG(1) << __FUNCTION__;
      delete http_transaction_factory_;
      delete http_auth_handler_factory_;
      delete cert_verifier_;
      delete host_resolver_;
    }

    void Initialize() {
      host_resolver_ =
          net::CreateSystemHostResolver(net::HostResolver::kDefaultParallelism,
                                        NULL, NULL);
      cert_verifier_ = new net::CertVerifier;
      net::ProxyConfigService* proxy_config_service =
          net::ProxyService::CreateSystemProxyConfigService(NULL, NULL);
      DCHECK(proxy_config_service);

      const size_t kNetLogBound = 50u;
      net_log_.reset(new net::CapturingNetLog(kNetLogBound));

      proxy_service_ = net::ProxyService::CreateUsingSystemProxyResolver(
          proxy_config_service, 0, net_log_.get());
      DCHECK(proxy_service_);

      ssl_config_service_ = new net::SSLConfigServiceDefaults;
      http_auth_handler_factory_ = net::HttpAuthHandlerFactory::CreateDefault(
          host_resolver_);
      http_transaction_factory_ = new net::HttpCache(
          net::HttpNetworkLayer::CreateFactory(host_resolver_,
                                               cert_verifier_,
                                               NULL /* dnsrr_resolver */,
                                               NULL /* dns_cert_checker */,
                                               NULL /* ssl_host_info_factory */,
                                               proxy_service_,
                                               ssl_config_service_,
                                               http_auth_handler_factory_,
                                               network_delegate_,
                                               NULL),
          net::HttpCache::DefaultBackend::InMemory(0));
    }

   private:
    scoped_ptr<net::NetLog> net_log_;
    scoped_ptr<net::URLSecurityManager> url_security_manager_;
  };

  PluginInstallerDownloadTest()
      : success_(false),
        download_helper_(NULL) {}
  ~PluginInstallerDownloadTest() {}

  void Start() {
    initial_download_path_ = PluginTest::GetTestUrl("flash.html", false);
    download_helper_ = new PluginDownloadUrlHelper(
        initial_download_path_.spec(), base::GetCurrentProcId(), NULL,
        static_cast<PluginDownloadUrlHelper::DownloadDelegate*>(this));
    download_helper_->InitiateDownload(new UploadRequestContext);

    MessageLoop::current()->PostDelayedTask(
        FROM_HERE, new MessageLoop::QuitTask,
        TestTimeouts::action_max_timeout_ms());
  }

  virtual void OnDownloadCompleted(const FilePath& download_path,
                                   bool success) {
    success_ = success;
    final_download_path_ = download_path;
    MessageLoop::current()->Quit();
    download_helper_ = NULL;
  }

  FilePath final_download_path() const {
    return final_download_path_;
  }

  FilePath initial_download_path() const {
    return final_download_path_;
  }

  bool success() const {
    return success_;
  }

 private:
  FilePath final_download_path_;
  PluginDownloadUrlHelper* download_helper_;
  bool success_;
  GURL initial_download_path_;
};

// This test validates that the plugin downloader downloads the specified file
// to a temporary path with the same file name.
TEST_F(PluginInstallerDownloadTest, PluginInstallerDownloadPathTest) {
  MessageLoop loop(MessageLoop::TYPE_IO);
  Start();
  loop.Run();

  EXPECT_TRUE(success());
  EXPECT_TRUE(initial_download_path().BaseName().value() ==
              final_download_path().BaseName().value());
}
#endif  // defined(OS_WIN)
<|endoftext|>


<commit_before>// @(#)root/pyroot:$Id$
// Author: Wim Lavrijsen, Jan 2005

// Bindings
#include "PyROOT.h"
#include "structmember.h"
#include "MethodProxy.h"
#include "ObjectProxy.h"
#include "TPyException.h"

// Standard
#include <algorithm>
#include <functional>
#include <vector>
#include <algorithm>

namespace PyROOT {

namespace {

// helper for collecting/maintaining exception data in overload dispatch
   struct PyError_t {
      PyError_t() { fType = fValue = fTrace = 0; }

      static void Clear( PyError_t& e )
      {
         Py_XDECREF( e.fType ); Py_XDECREF( e.fValue ); Py_XDECREF( e.fTrace );
         e.fType = e.fValue = e.fTrace = 0;
      }

      PyObject *fType, *fValue, *fTrace;
   };

// helper to hash tuple (using tuple hash would cause self-tailing loops)
   inline Long_t HashSignature( PyObject* args )
   {
      ULong_t hash = 0;

      Int_t nargs = PyTuple_GET_SIZE( args );
      for ( Int_t i = 0; i < nargs; ++i ) {
         hash += (ULong_t) PyTuple_GET_ITEM( args, i )->ob_type;
         hash += (hash << 10); hash ^= (hash >> 6);
      }

      hash += (hash << 3); hash ^= (hash >> 11); hash += (hash << 15);

      return hash;
   }

// helper to sort on method priority
   int PriorityCmp( PyCallable* left, PyCallable* right )
   {
      return left->GetPriority() > right->GetPriority();
   }

// helper to factor out return logic of mp_call
   inline PyObject* HandleReturn( MethodProxy* meth, PyObject* result ) {

   // special case for python exceptions, propagated through C++ layer
      if ( result == (PyObject*)TPyExceptionMagic )
         return 0;              // exception info was already set

   // if this is creates new objects, always take ownership
      if ( ( meth->fMethodInfo->fFlags & MethodProxy::MethodInfo_t::kIsCreator ) &&
           ObjectProxy_Check( result ) )
         ((ObjectProxy*)result)->HoldOn();

      return result;
   }

//= PyROOT method proxy object behaviour =====================================
   PyObject* mp_name( MethodProxy* meth, void* )
   {
      return PyString_FromString( meth->GetName().c_str() );
   }

//____________________________________________________________________________
   PyObject* mp_doc( MethodProxy* meth, void* )
   {
      MethodProxy::Methods_t& methods = meth->fMethodInfo->fMethods;

   // collect doc strings
      Int_t nMethods = methods.size();
      PyObject* doc = methods[0]->GetDocString();

   // simple case
      if ( nMethods == 1 )
         return doc;

   // overloaded method
      PyObject* separator = PyString_FromString( "\n" );
      for ( Int_t i = 1; i < nMethods; ++i ) {
         PyString_Concat( &doc, separator );
         PyString_ConcatAndDel( &doc, methods[i]->GetDocString() );
      }
      Py_DECREF( separator );

      return doc;
   }

//____________________________________________________________________________
   PyObject* mp_getcreates( MethodProxy* meth, void* )
   {
      return PyInt_FromLong(
         (Bool_t)(meth->fMethodInfo->fFlags & MethodProxy::MethodInfo_t::kIsCreator ) );
   }

//____________________________________________________________________________
   int mp_setcreates( MethodProxy* meth, PyObject* value, void* )
   {
      Long_t iscreator = PyLong_AsLong( value );
      if ( iscreator == -1 && PyErr_Occurred() ) {
         PyErr_SetString( PyExc_ValueError, "a boolean 1 or 0 is required for _creates" );
         return -1;
      }

      if ( iscreator )
         meth->fMethodInfo->fFlags |= MethodProxy::MethodInfo_t::kIsCreator;
      else
         meth->fMethodInfo->fFlags &= ~MethodProxy::MethodInfo_t::kIsCreator;

      return 0;
   }

//____________________________________________________________________________
   PyGetSetDef mp_getset[] = {
      { (char*)"__name__", (getter)mp_name, NULL, NULL, NULL },
      { (char*)"__doc__", (getter)mp_doc, NULL, NULL, NULL },
      { (char*)"_creates", (getter)mp_getcreates, (setter)mp_setcreates,
            (char*)"For ownership rules of result: if true, objects are python-owned", NULL },
      { (char*)NULL, NULL, NULL, NULL, NULL }
   };

//= PyROOT method proxy function behavior ====================================
   PyObject* mp_call( MethodProxy* meth, PyObject* args, PyObject* kwds )
   {
   // get local handles to proxy internals
      MethodProxy::Methods_t&     methods     = meth->fMethodInfo->fMethods;
      MethodProxy::DispatchMap_t& dispatchMap = meth->fMethodInfo->fDispatchMap;

      Int_t nMethods = methods.size();

   // simple case
      if ( nMethods == 1 )
         return HandleReturn( meth, (*methods[0])( meth->fSelf, args, kwds ) );

   // otherwise, handle overloading
      Long_t sighash = HashSignature( args );

   // look for known signatures ...
      MethodProxy::DispatchMap_t::iterator m = dispatchMap.find( sighash );
      if ( m != dispatchMap.end() ) {
         Int_t index = m->second;
         PyObject* result = HandleReturn( meth, (*methods[ index ])( meth->fSelf, args, kwds ) );
         if ( result != 0 )
            return result;

      // fall through: python is dynamic, and so, the hashing isn't infallible
         PyErr_Clear();
      }

   // ... otherwise loop over all methods and find the one that does not fail
      if ( ! ( meth->fMethodInfo->fFlags & MethodProxy::MethodInfo_t::kIsSorted ) ) {
         std::stable_sort( methods.begin(), methods.end(), PriorityCmp );
         meth->fMethodInfo->fFlags |= MethodProxy::MethodInfo_t::kIsSorted;
      }

      std::vector< PyError_t > errors;
      for ( Int_t i = 0; i < nMethods; ++i ) {
         PyObject* result = (*methods[i])( meth->fSelf, args, kwds );

         if ( result == (PyObject*)TPyExceptionMagic ) {
            std::for_each( errors.begin(), errors.end(), PyError_t::Clear );
            return 0;              // exception info was already set
         }

         if ( result != 0 ) {
         // success: update the dispatch map for subsequent calls
            dispatchMap[ sighash ] = i;
            std::for_each( errors.begin(), errors.end(), PyError_t::Clear );
            return HandleReturn( meth, result );
         }

      // failure: collect error message/trace (automatically clears exception, too)
         if ( ! PyErr_Occurred() ) {
         // this should not happen; set an error to prevent core dump and report
            PyObject* sig = methods[i]->GetPrototype();
            PyErr_Format( PyExc_SystemError, "%s =>\n    %s",
               PyString_AS_STRING( sig ), (char*)"NULL result without error in mp_call" );
            Py_DECREF( sig );
         }
         PyError_t e;
         PyErr_Fetch( &e.fType, &e.fValue, &e.fTrace );
         errors.push_back( e );
      }

   // first summarize, then add details
      PyObject* value = PyString_FromFormat(
         "none of the %d overloaded methods succeeded. Full details:", nMethods );
      PyObject* separator = PyString_FromString( "\n  " );

   // if this point is reached, none of the overloads succeeded: notify user
      for ( std::vector< PyError_t >::iterator e = errors.begin(); e != errors.end(); ++e ) {
         PyString_Concat( &value, separator );
         PyString_Concat( &value, e->fValue );
      }

      Py_DECREF( separator );
      std::for_each( errors.begin(), errors.end(), PyError_t::Clear );

   // report failure
      PyErr_SetObject( PyExc_TypeError, value );
      Py_DECREF( value );
      return 0;
   }

//____________________________________________________________________________
   MethodProxy* mp_descrget( MethodProxy* pymeth, ObjectProxy* pyobj, PyObject* )
   {
   // create and use a new method proxy (language requirement)
      MethodProxy* newPyMeth = (MethodProxy*)MethodProxy_Type.tp_alloc( &MethodProxy_Type, 0 );

   // method info is shared, as it contains the collected overload knowledge
      *pymeth->fMethodInfo->fRefCount += 1;
      newPyMeth->fMethodInfo = pymeth->fMethodInfo;

   // new method is to be bound to current object (may be NULL)
      Py_XINCREF( (PyObject*)pyobj );
      newPyMeth->fSelf = pyobj;

      return newPyMeth;
   }

//= PyROOT method proxy construction/destruction =================================
   MethodProxy* mp_new( PyTypeObject*, PyObject*, PyObject* )
   {
      MethodProxy* pymeth = PyObject_GC_New( MethodProxy, &MethodProxy_Type );
      pymeth->fSelf = NULL;
      pymeth->fMethodInfo = new MethodProxy::MethodInfo_t;

      PyObject_GC_Track( pymeth );
      return pymeth;
   }

//____________________________________________________________________________
   void mp_dealloc( MethodProxy* pymeth )
   {
      PyObject_GC_UnTrack( pymeth );

      Py_XDECREF( (PyObject*)pymeth->fSelf );
      pymeth->fSelf = NULL;

      if ( --(*pymeth->fMethodInfo->fRefCount) <= 0 ) {
         delete pymeth->fMethodInfo;
      }

      PyObject_GC_Del( pymeth );
   }

//____________________________________________________________________________
   int mp_traverse( MethodProxy* pymeth, visitproc visit, void* args )
   {
      if ( pymeth->fSelf )
         return visit( (PyObject*)pymeth->fSelf, args );

      return 0;
   }

//____________________________________________________________________________
   int mp_clear( MethodProxy* pymeth )
   {
      Py_XDECREF( (PyObject*)pymeth->fSelf );
      pymeth->fSelf = NULL;

      return 0;
   }

//= PyROOT method proxy access to internals =================================
   PyObject* mp_disp( MethodProxy* meth, PyObject* args, PyObject* )
   {
      PyObject* sigarg = 0;
      if ( ! PyArg_ParseTuple( args, const_cast< char* >( "S:disp" ), &sigarg ) )
         return 0;

      PyObject* sig1 = PyString_FromFormat( "(%s)", PyString_AS_STRING( sigarg ) );

      MethodProxy::Methods_t& methods = meth->fMethodInfo->fMethods;
      for ( Int_t i = 0; i < (Int_t)methods.size(); ++i ) {
         PyObject* sig2 = methods[ i ]->GetSignature();
         if ( PyObject_Compare( sig1, sig2 ) == 0 ) {
            Py_DECREF( sig2 );

            MethodProxy* newmeth = mp_new( NULL, NULL, NULL );
            MethodProxy::Methods_t vec; vec.push_back( methods[ i ] );
            newmeth->Set( meth->fMethodInfo->fName, vec );

            Py_DECREF( sig1 );
            return (PyObject*)newmeth;
         }

         Py_DECREF( sig2 );
      }

      Py_DECREF( sig1 );
      PyErr_Format( PyExc_LookupError, "signature \"%s\" not found", PyString_AS_STRING( sigarg ) );
      return 0;
   }

//____________________________________________________________________________
   PyMethodDef mp_methods[] = {
      { (char*)"disp", (PyCFunction)mp_disp, METH_VARARGS, (char*)"select overload for dispatch" },
      { (char*)NULL, NULL, 0, NULL }
   };

} // unnamed namespace

//= PyROOT method proxy type =================================================
PyTypeObject MethodProxy_Type = {
   PyObject_HEAD_INIT( &PyType_Type )
   0,                         // ob_size
   (char*)"ROOT.MethodProxy", // tp_name
   sizeof(MethodProxy),       // tp_basicsize
   0,                         // tp_itemsize
   (destructor)mp_dealloc,    // tp_dealloc
   0,                         // tp_print
   0,                         // tp_getattr
   0,                         // tp_setattr
   0,                         // tp_compare
   0,                         // tp_repr
   0,                         // tp_as_number
   0,                         // tp_as_sequence
   0,                         // tp_as_mapping
   0,                         // tp_hash
   (ternaryfunc)mp_call,      // tp_call
   0,                         // tp_str
   0,                         // tp_getattro
   0,                         // tp_setattro
   0,                         // tp_as_buffer
   Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,      // tp_flags
   (char*)"PyROOT method proxy (internal)",      // tp_doc
   (traverseproc)mp_traverse, // tp_traverse
   (inquiry)mp_clear,         // tp_clear
   0,                         // tp_richcompare
   0,                         // tp_weaklistoffset
   0,                         // tp_iter
   0,                         // tp_iternext
   mp_methods,                // tp_methods
   0,                         // tp_members
   mp_getset,                 // tp_getset
   0,                         // tp_base
   0,                         // tp_dict
   (descrgetfunc)mp_descrget, // tp_descr_get
   0,                         // tp_descr_set
   0,                         // tp_dictoffset
   0,                         // tp_init
   0,                         // tp_alloc
   (newfunc)mp_new,           // tp_new
   0,                         // tp_free
   0,                         // tp_is_gc
   0,                         // tp_bases
   0,                         // tp_mro
   0,                         // tp_cache
   0,                         // tp_subclasses
   0,                         // tp_weaklist

#if PY_MAJOR_VERSION >= 2 && PY_MINOR_VERSION >= 3
   0                          // tp_del
#endif
};

} // namespace PyROOT

//- public members -----------------------------------------------------------
void PyROOT::MethodProxy::Set( const std::string& name, std::vector< PyCallable* >& methods )
{
// set method data
   fMethodInfo->fName = name;
   fMethodInfo->fMethods.swap( methods );
   fMethodInfo->fFlags &= ~MethodInfo_t::kIsSorted;
}

//____________________________________________________________________________
PyROOT::MethodProxy::MethodInfo_t::~MethodInfo_t()
{
   for ( Methods_t::iterator it = fMethods.begin(); it != fMethods.end(); ++it ) {
      delete *it;
   }
   fMethods.clear();
   delete fRefCount;
}
<commit_msg> o) Clone() and DrawClone() should return objects that are owned<commit_after>// @(#)root/pyroot:$Id$
// Author: Wim Lavrijsen, Jan 2005

// Bindings
#include "PyROOT.h"
#include "structmember.h"
#include "MethodProxy.h"
#include "ObjectProxy.h"
#include "TPyException.h"
#include "Utility.h"

// Standard
#include <algorithm>
#include <functional>
#include <vector>
#include <algorithm>

namespace PyROOT {

namespace {

// helper for collecting/maintaining exception data in overload dispatch
   struct PyError_t {
      PyError_t() { fType = fValue = fTrace = 0; }

      static void Clear( PyError_t& e )
      {
         Py_XDECREF( e.fType ); Py_XDECREF( e.fValue ); Py_XDECREF( e.fTrace );
         e.fType = e.fValue = e.fTrace = 0;
      }

      PyObject *fType, *fValue, *fTrace;
   };

// helper to hash tuple (using tuple hash would cause self-tailing loops)
   inline Long_t HashSignature( PyObject* args )
   {
      ULong_t hash = 0;

      Int_t nargs = PyTuple_GET_SIZE( args );
      for ( Int_t i = 0; i < nargs; ++i ) {
         hash += (ULong_t) PyTuple_GET_ITEM( args, i )->ob_type;
         hash += (hash << 10); hash ^= (hash >> 6);
      }

      hash += (hash << 3); hash ^= (hash >> 11); hash += (hash << 15);

      return hash;
   }

// helper to sort on method priority
   int PriorityCmp( PyCallable* left, PyCallable* right )
   {
      return left->GetPriority() > right->GetPriority();
   }

// helper to factor out return logic of mp_call
   inline PyObject* HandleReturn( MethodProxy* meth, PyObject* result ) {

   // special case for python exceptions, propagated through C++ layer
      if ( result == (PyObject*)TPyExceptionMagic )
         return 0;              // exception info was already set

   // if this is creates new objects, always take ownership
      if ( ( meth->fMethodInfo->fFlags & MethodProxy::MethodInfo_t::kIsCreator ) &&
           ObjectProxy_Check( result ) )
         ((ObjectProxy*)result)->HoldOn();

      return result;
   }

//= PyROOT method proxy object behaviour =====================================
   PyObject* mp_name( MethodProxy* meth, void* )
   {
      return PyString_FromString( meth->GetName().c_str() );
   }

//____________________________________________________________________________
   PyObject* mp_doc( MethodProxy* meth, void* )
   {
      MethodProxy::Methods_t& methods = meth->fMethodInfo->fMethods;

   // collect doc strings
      Int_t nMethods = methods.size();
      PyObject* doc = methods[0]->GetDocString();

   // simple case
      if ( nMethods == 1 )
         return doc;

   // overloaded method
      PyObject* separator = PyString_FromString( "\n" );
      for ( Int_t i = 1; i < nMethods; ++i ) {
         PyString_Concat( &doc, separator );
         PyString_ConcatAndDel( &doc, methods[i]->GetDocString() );
      }
      Py_DECREF( separator );

      return doc;
   }

//____________________________________________________________________________
   PyObject* mp_getcreates( MethodProxy* meth, void* )
   {
      return PyInt_FromLong(
         (Bool_t)(meth->fMethodInfo->fFlags & MethodProxy::MethodInfo_t::kIsCreator ) );
   }

//____________________________________________________________________________
   int mp_setcreates( MethodProxy* meth, PyObject* value, void* )
   {
      Long_t iscreator = PyLong_AsLong( value );
      if ( iscreator == -1 && PyErr_Occurred() ) {
         PyErr_SetString( PyExc_ValueError, "a boolean 1 or 0 is required for _creates" );
         return -1;
      }

      if ( iscreator )
         meth->fMethodInfo->fFlags |= MethodProxy::MethodInfo_t::kIsCreator;
      else
         meth->fMethodInfo->fFlags &= ~MethodProxy::MethodInfo_t::kIsCreator;

      return 0;
   }

//____________________________________________________________________________
   PyGetSetDef mp_getset[] = {
      { (char*)"__name__", (getter)mp_name, NULL, NULL, NULL },
      { (char*)"__doc__", (getter)mp_doc, NULL, NULL, NULL },
      { (char*)"_creates", (getter)mp_getcreates, (setter)mp_setcreates,
            (char*)"For ownership rules of result: if true, objects are python-owned", NULL },
      { (char*)NULL, NULL, NULL, NULL, NULL }
   };

//= PyROOT method proxy function behavior ====================================
   PyObject* mp_call( MethodProxy* meth, PyObject* args, PyObject* kwds )
   {
   // get local handles to proxy internals
      MethodProxy::Methods_t&     methods     = meth->fMethodInfo->fMethods;
      MethodProxy::DispatchMap_t& dispatchMap = meth->fMethodInfo->fDispatchMap;

      Int_t nMethods = methods.size();

   // simple case
      if ( nMethods == 1 )
         return HandleReturn( meth, (*methods[0])( meth->fSelf, args, kwds ) );

   // otherwise, handle overloading
      Long_t sighash = HashSignature( args );

   // look for known signatures ...
      MethodProxy::DispatchMap_t::iterator m = dispatchMap.find( sighash );
      if ( m != dispatchMap.end() ) {
         Int_t index = m->second;
         PyObject* result = HandleReturn( meth, (*methods[ index ])( meth->fSelf, args, kwds ) );
         if ( result != 0 )
            return result;

      // fall through: python is dynamic, and so, the hashing isn't infallible
         PyErr_Clear();
      }

   // ... otherwise loop over all methods and find the one that does not fail
      if ( ! ( meth->fMethodInfo->fFlags & MethodProxy::MethodInfo_t::kIsSorted ) ) {
         std::stable_sort( methods.begin(), methods.end(), PriorityCmp );
         meth->fMethodInfo->fFlags |= MethodProxy::MethodInfo_t::kIsSorted;
      }

      std::vector< PyError_t > errors;
      for ( Int_t i = 0; i < nMethods; ++i ) {
         PyObject* result = (*methods[i])( meth->fSelf, args, kwds );

         if ( result == (PyObject*)TPyExceptionMagic ) {
            std::for_each( errors.begin(), errors.end(), PyError_t::Clear );
            return 0;              // exception info was already set
         }

         if ( result != 0 ) {
         // success: update the dispatch map for subsequent calls
            dispatchMap[ sighash ] = i;
            std::for_each( errors.begin(), errors.end(), PyError_t::Clear );
            return HandleReturn( meth, result );
         }

      // failure: collect error message/trace (automatically clears exception, too)
         if ( ! PyErr_Occurred() ) {
         // this should not happen; set an error to prevent core dump and report
            PyObject* sig = methods[i]->GetPrototype();
            PyErr_Format( PyExc_SystemError, "%s =>\n    %s",
               PyString_AS_STRING( sig ), (char*)"NULL result without error in mp_call" );
            Py_DECREF( sig );
         }
         PyError_t e;
         PyErr_Fetch( &e.fType, &e.fValue, &e.fTrace );
         errors.push_back( e );
      }

   // first summarize, then add details
      PyObject* value = PyString_FromFormat(
         "none of the %d overloaded methods succeeded. Full details:", nMethods );
      PyObject* separator = PyString_FromString( "\n  " );

   // if this point is reached, none of the overloads succeeded: notify user
      for ( std::vector< PyError_t >::iterator e = errors.begin(); e != errors.end(); ++e ) {
         PyString_Concat( &value, separator );
         PyString_Concat( &value, e->fValue );
      }

      Py_DECREF( separator );
      std::for_each( errors.begin(), errors.end(), PyError_t::Clear );

   // report failure
      PyErr_SetObject( PyExc_TypeError, value );
      Py_DECREF( value );
      return 0;
   }

//____________________________________________________________________________
   MethodProxy* mp_descrget( MethodProxy* pymeth, ObjectProxy* pyobj, PyObject* )
   {
   // create and use a new method proxy (language requirement)
      MethodProxy* newPyMeth = (MethodProxy*)MethodProxy_Type.tp_alloc( &MethodProxy_Type, 0 );

   // method info is shared, as it contains the collected overload knowledge
      *pymeth->fMethodInfo->fRefCount += 1;
      newPyMeth->fMethodInfo = pymeth->fMethodInfo;

   // new method is to be bound to current object (may be NULL)
      Py_XINCREF( (PyObject*)pyobj );
      newPyMeth->fSelf = pyobj;

      return newPyMeth;
   }

//= PyROOT method proxy construction/destruction =================================
   MethodProxy* mp_new( PyTypeObject*, PyObject*, PyObject* )
   {
      MethodProxy* pymeth = PyObject_GC_New( MethodProxy, &MethodProxy_Type );
      pymeth->fSelf = NULL;
      pymeth->fMethodInfo = new MethodProxy::MethodInfo_t;

      PyObject_GC_Track( pymeth );
      return pymeth;
   }

//____________________________________________________________________________
   void mp_dealloc( MethodProxy* pymeth )
   {
      PyObject_GC_UnTrack( pymeth );

      Py_XDECREF( (PyObject*)pymeth->fSelf );
      pymeth->fSelf = NULL;

      if ( --(*pymeth->fMethodInfo->fRefCount) <= 0 ) {
         delete pymeth->fMethodInfo;
      }

      PyObject_GC_Del( pymeth );
   }

//____________________________________________________________________________
   int mp_traverse( MethodProxy* pymeth, visitproc visit, void* args )
   {
      if ( pymeth->fSelf )
         return visit( (PyObject*)pymeth->fSelf, args );

      return 0;
   }

//____________________________________________________________________________
   int mp_clear( MethodProxy* pymeth )
   {
      Py_XDECREF( (PyObject*)pymeth->fSelf );
      pymeth->fSelf = NULL;

      return 0;
   }

//= PyROOT method proxy access to internals =================================
   PyObject* mp_disp( MethodProxy* meth, PyObject* args, PyObject* )
   {
      PyObject* sigarg = 0;
      if ( ! PyArg_ParseTuple( args, const_cast< char* >( "S:disp" ), &sigarg ) )
         return 0;

      PyObject* sig1 = PyString_FromFormat( "(%s)", PyString_AS_STRING( sigarg ) );

      MethodProxy::Methods_t& methods = meth->fMethodInfo->fMethods;
      for ( Int_t i = 0; i < (Int_t)methods.size(); ++i ) {
         PyObject* sig2 = methods[ i ]->GetSignature();
         if ( PyObject_Compare( sig1, sig2 ) == 0 ) {
            Py_DECREF( sig2 );

            MethodProxy* newmeth = mp_new( NULL, NULL, NULL );
            MethodProxy::Methods_t vec; vec.push_back( methods[ i ] );
            newmeth->Set( meth->fMethodInfo->fName, vec );

            Py_DECREF( sig1 );
            return (PyObject*)newmeth;
         }

         Py_DECREF( sig2 );
      }

      Py_DECREF( sig1 );
      PyErr_Format( PyExc_LookupError, "signature \"%s\" not found", PyString_AS_STRING( sigarg ) );
      return 0;
   }

//____________________________________________________________________________
   PyMethodDef mp_methods[] = {
      { (char*)"disp", (PyCFunction)mp_disp, METH_VARARGS, (char*)"select overload for dispatch" },
      { (char*)NULL, NULL, 0, NULL }
   };

} // unnamed namespace

//= PyROOT method proxy type =================================================
PyTypeObject MethodProxy_Type = {
   PyObject_HEAD_INIT( &PyType_Type )
   0,                         // ob_size
   (char*)"ROOT.MethodProxy", // tp_name
   sizeof(MethodProxy),       // tp_basicsize
   0,                         // tp_itemsize
   (destructor)mp_dealloc,    // tp_dealloc
   0,                         // tp_print
   0,                         // tp_getattr
   0,                         // tp_setattr
   0,                         // tp_compare
   0,                         // tp_repr
   0,                         // tp_as_number
   0,                         // tp_as_sequence
   0,                         // tp_as_mapping
   0,                         // tp_hash
   (ternaryfunc)mp_call,      // tp_call
   0,                         // tp_str
   0,                         // tp_getattro
   0,                         // tp_setattro
   0,                         // tp_as_buffer
   Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,      // tp_flags
   (char*)"PyROOT method proxy (internal)",      // tp_doc
   (traverseproc)mp_traverse, // tp_traverse
   (inquiry)mp_clear,         // tp_clear
   0,                         // tp_richcompare
   0,                         // tp_weaklistoffset
   0,                         // tp_iter
   0,                         // tp_iternext
   mp_methods,                // tp_methods
   0,                         // tp_members
   mp_getset,                 // tp_getset
   0,                         // tp_base
   0,                         // tp_dict
   (descrgetfunc)mp_descrget, // tp_descr_get
   0,                         // tp_descr_set
   0,                         // tp_dictoffset
   0,                         // tp_init
   0,                         // tp_alloc
   (newfunc)mp_new,           // tp_new
   0,                         // tp_free
   0,                         // tp_is_gc
   0,                         // tp_bases
   0,                         // tp_mro
   0,                         // tp_cache
   0,                         // tp_subclasses
   0,                         // tp_weaklist

#if PY_MAJOR_VERSION >= 2 && PY_MINOR_VERSION >= 3
   0                          // tp_del
#endif
};

} // namespace PyROOT

//- public members -----------------------------------------------------------
void PyROOT::MethodProxy::Set( const std::string& name, std::vector< PyCallable* >& methods )
{
// set method data
   fMethodInfo->fName = name;
   fMethodInfo->fMethods.swap( methods );
   fMethodInfo->fFlags &= ~MethodInfo_t::kIsSorted;

// special case, in heuristics mode also tag *Clone* methods as creators
   if ( Utility::gMemoryPolicy == Utility::kHeuristics && name.find( "Clone" ) != std::string::npos )
      fMethodInfo->fFlags |= MethodInfo_t::kIsCreator;
}

//____________________________________________________________________________
PyROOT::MethodProxy::MethodInfo_t::~MethodInfo_t()
{
   for ( Methods_t::iterator it = fMethods.begin(); it != fMethods.end(); ++it ) {
      delete *it;
   }
   fMethods.clear();
   delete fRefCount;
}
<|endoftext|>


<commit_before>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include <Utils/TestUtils.hpp>
#include "gtest/gtest.h"

#include <hspp/Cards/Minion.hpp>
#include <hspp/Managers/GameAgent.hpp>
#include <hspp/Tasks/SimpleTasks/ControlTask.hpp>

using namespace Hearthstonepp;
using namespace SimpleTasks;
using namespace TestUtils;

TEST(ControlTask, GetTaskID)
{
    const ControlTask control(EntityType::TARGET);
    EXPECT_EQ(control.GetTaskID(), +TaskID::CONTROL);
}

TEST(ControlTask, Run)
{
    GameAgent agent(CardClass::ROGUE, CardClass::DRUID, PlayerType::PLAYER1);
    Player& player1 = agent.GetPlayer1();
    Player& player2 = agent.GetPlayer2();

    auto& player1Field = player1.GetField();
    auto& player2Field = player2.GetField();

    std::vector<Card> cards;
    cards.reserve(5);

    const std::string name = "test";
    for (size_t i = 0; i < 6; ++i)
    {
        const auto id = static_cast<char>(i + 0x30);
        cards.emplace_back(GenerateMinionCard(name + id, 1, 1));
        PlayMinionCard(player1, cards[i]);
        PlayMinionCard(player2, cards[i]);
    }

    ControlTask control(EntityType::TARGET);
    control.SetTarget(player2Field.GetMinion(0));
    MetaData result = control.Run(player1);

    EXPECT_EQ(result, MetaData::CONTROL_SUCCESS);
    EXPECT_EQ(player1Field.GetNumOfMinions(), 7u);
    EXPECT_EQ(player2Field.GetNumOfMinions(), 5u);

    control.SetTarget(player2Field.GetMinion(1));
    result = control.Run(player1);

    EXPECT_EQ(result, MetaData::CONTROL_FIELD_IS_FULL);
    EXPECT_EQ(player1Field.GetNumOfMinions(), 7u);
    EXPECT_EQ(player2Field.GetNumOfMinions(), 5u);
}
<commit_msg>test: Add unit tests for checking valid data<commit_after>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include <Utils/TestUtils.hpp>
#include "gtest/gtest.h"

#include <hspp/Cards/Minion.hpp>
#include <hspp/Managers/GameAgent.hpp>
#include <hspp/Tasks/SimpleTasks/ControlTask.hpp>

using namespace Hearthstonepp;
using namespace SimpleTasks;
using namespace TestUtils;

TEST(ControlTask, GetTaskID)
{
    const ControlTask control(EntityType::TARGET);
    EXPECT_EQ(control.GetTaskID(), +TaskID::CONTROL);
}

TEST(ControlTask, Run)
{
    GameAgent agent(CardClass::ROGUE, CardClass::DRUID, PlayerType::PLAYER1);
    Player& player1 = agent.GetPlayer1();
    Player& player2 = agent.GetPlayer2();

    auto& player1Field = player1.GetField();
    auto& player2Field = player2.GetField();

    std::vector<Card> cards;
    cards.reserve(5);

    const std::string name = "test";
    for (size_t i = 0; i < 6; ++i)
    {
        const auto id = static_cast<char>(i + 0x30);
        cards.emplace_back(GenerateMinionCard(name + id, 1, 1));
        PlayMinionCard(player1, cards[i]);
        PlayMinionCard(player2, cards[i]);
    }

    ControlTask control(EntityType::TARGET);
    control.SetTarget(player2Field.GetMinion(0));
    MetaData result = control.Run(player1);

    EXPECT_EQ(result, MetaData::CONTROL_SUCCESS);
    EXPECT_EQ(player1Field.GetNumOfMinions(), 7u);
    EXPECT_EQ(player2Field.GetNumOfMinions(), 5u);

    // Check controlled minion has valid data
    EXPECT_EQ(player1Field.GetMinion(6)->GetAttack(), 1);
    EXPECT_EQ(player1Field.GetMinion(6)->health, 1);

    control.SetTarget(player2Field.GetMinion(1));
    result = control.Run(player1);

    EXPECT_EQ(result, MetaData::CONTROL_FIELD_IS_FULL);
    EXPECT_EQ(player1Field.GetNumOfMinions(), 7u);
    EXPECT_EQ(player2Field.GetNumOfMinions(), 5u);
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#include "utils/file_reader.h"
#include <string>
#include <iostream>
#include <cstdint>
#include <grpcpp/grpcpp.h>
#include <grpcpp/channel.h>
#include <grpcpp/client_context.h>
#include <grpcpp/create_channel.h>
#include <grpcpp/security/credentials.h>
#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "proto/usps_api/sfc.grpc.pb.h"

ABSL_FLAG(std::string, HOST, "localhost", "The host of the ip to listen on");
// port will be within range due to flag definition
ABSL_FLAG(std::uint16_t, PORT, 0, "The port of the ip to listen on");
namespace usps_api_client {
  namespace {
    class GhostClient {
      public:
       GhostClient(std::shared_ptr<grpc::Channel> channel)
           : stub_(ghost::SfcService::NewStub(channel)) {}

       // Send a CreateSfc Request to server.
       void CreateSfc(grpc::ClientContext* context,
                      ghost::CreateSfcRequest request,
                      ghost::CreateSfcResponse* response) {
         grpc::Status status = stub_->CreateSfc(context, request, response);
         if(!status.ok()) {
           std::cout << "Failed to create SFC" << std::endl;
         } else {
           std::cout << "Successfully created SFC" << std::endl;
         }
       }
       // Send a DeleteSfc Request to server.
       void DeleteSfc(grpc::ClientContext* context,
                      ghost::DeleteSfcRequest request,
                      ghost::DeleteSfcResponse* response) {
         grpc::Status status = stub_->DeleteSfc(context, request, response);
         if(!status.ok()) {
           std::cout << "Failed to create SFC" << std::endl;
         } else {
           std::cout << "Successfully created SFC" << std::endl;
         }
       }
       // Send a QuerySfc Request to server.
       void Query(grpc::ClientContext* context,
                      ghost::QueryRequest request,
                      ghost::QueryResponse* response) {
         grpc::Status status = stub_->Query(context, request, response);
         if(!status.ok()) {
           std::cout << "Failed to create SFC" << std::endl;
         } else {
           std::cout << "Successfully created SFC" << std::endl;
         }
       }
      private:
        std::unique_ptr<ghost::SfcService::Stub> stub_;
    };
    // Creates a modifiable GhostFilter at a given request.
    ghost::GhostFilter* GetFilter(ghost::CreateSfcRequest* request) {
      ghost::SfcFilter* sfc_filter = request->mutable_sfc_filter();
      ghost::FilterLayer* layer = sfc_filter->add_filter_layers();
      ghost::GhostFilter* filter = layer->mutable_ghost_filter();
      return filter;
    }
    // Creates SfcRequest using GhostTunnelIdentifier as a filter
    void CreateSfcTunnel(GhostClient* client,
                         std::uint64_t terminal_value,
                         std::uint64_t service_value) {
      grpc::ClientContext context;
      ghost::CreateSfcRequest request;
      ghost::CreateSfcResponse response;
      ghost::GhostFilter* filter = GetFilter(&request);
      ghost::GhostTunnelIdentifier* tunnel_id = filter->mutable_tunnel_id();
      ghost::GhostLabel* terminal_label = tunnel_id->mutable_terminal_label();;
      ghost::GhostLabel* service_label = tunnel_id->mutable_service_label();
      terminal_label->set_value(terminal_value);
      service_label->set_value(service_value);
      client->CreateSfc(&context, request, &response);
    }
    // Creates Sfc using GhostRoutingIdentifier as a filter
    void CreateSfcRoute(GhostClient* client,
                         std::uint64_t value,
                         std::uint32_t prefix_len) {
      grpc::ClientContext context;
      ghost::CreateSfcRequest request;
      ghost::CreateSfcResponse response;
      ghost::GhostFilter* filter = GetFilter(&request);
      ghost::GhostRoutingIdentifier* routing_id = filter->mutable_routing_id();
      ghost::GhostLabelPrefix* dest_label_prefix = routing_id->mutable_destination_label_prefix();
      dest_label_prefix->set_value(value);
      dest_label_prefix->set_prefix_len(prefix_len);
      client->CreateSfc(&context, request, &response);
    }
    std::shared_ptr<grpc::ChannelCredentials> GetCreds(std::string key_file,
                                                       std::string key_cert,
                                                       std::string key_root) {
      std::string key = FileReader::ReadString(key_file);
      std::string cert = FileReader::ReadString(key_cert);
      std::string root = FileReader::ReadString(key_root);
      grpc::SslCredentialsOptions ssl_opts;
      ssl_opts.pem_root_certs = root;
      ssl_opts.pem_cert_chain = cert;
      ssl_opts.pem_private_key = key;
      return grpc::SslCredentials(ssl_opts);
    }
  }
}

int main(int argc, char** argv) {
  absl::ParseCommandLine(argc, argv);
  std::string server_address = absl::GetFlag(FLAGS_HOST) + ":" +
      std::to_string(absl::GetFlag(FLAGS_PORT));
  std::shared_ptr<grpc::ChannelCredentials> creds = grpc::InsecureChannelCredentials();
  usps_api_client::GhostClient client(
      grpc::CreateChannel(server_address, creds));
  return 0;
}
<commit_msg>added ghost namespace to client<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#include "utils/file_reader.h"
#include <string>
#include <iostream>
#include <cstdint>
#include <grpcpp/grpcpp.h>
#include <grpcpp/channel.h>
#include <grpcpp/client_context.h>
#include <grpcpp/create_channel.h>
#include <grpcpp/security/credentials.h>
#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "proto/usps_api/sfc.grpc.pb.h"

using namespace ghost;

ABSL_FLAG(std::string, HOST, "localhost", "The host of the ip to listen on");
// port will be within range due to flag definition
ABSL_FLAG(std::uint16_t, PORT, 0, "The port of the ip to listen on");
namespace usps_api_client {
  namespace {
    class GhostClient {
      public:
       GhostClient(std::shared_ptr<grpc::Channel> channel)
           : stub_(SfcService::NewStub(channel)) {}

       // Send a CreateSfc Request to server.
       void CreateSfc(grpc::ClientContext* context,
                      CreateSfcRequest request,
                      CreateSfcResponse* response) {
         grpc::Status status = stub_->CreateSfc(context, request, response);
         if(!status.ok()) {
           std::cout << "Failed to create SFC" << std::endl;
         } else {
           std::cout << "Successfully created SFC" << std::endl;
         }
       }
       // Send a DeleteSfc Request to server.
       void DeleteSfc(grpc::ClientContext* context,
                      DeleteSfcRequest request,
                      DeleteSfcResponse* response) {
         grpc::Status status = stub_->DeleteSfc(context, request, response);
         if(!status.ok()) {
           std::cout << "Failed to delete SFC" << std::endl;
         } else {
           std::cout << "Successfully created SFC" << std::endl;
         }
       }
       // Send a QuerySfc Request to server.
       void Query(grpc::ClientContext* context,
                      QueryRequest request,
                      QueryResponse* response) {
         grpc::Status status = stub_->Query(context, request, response);
         if(!status.ok()) {
           std::cout << "Failed to query SFC" << std::endl;
         } else {
           std::cout << "Successfully queried SFC" << std::endl;
         }
       }
      private:
        std::unique_ptr<SfcService::Stub> stub_;
    };
    // Creates a modifiable GhostFilter at a given request.
    GhostFilter* GetFilter(CreateSfcRequest* request) {
      SfcFilter* sfc_filter = request->mutable_sfc_filter();
      FilterLayer* layer = sfc_filter->add_filter_layers();
      GhostFilter* filter = layer->mutable_ghost_filter();
      return filter;
    }
    // Creates SfcRequest using GhostTunnelIdentifier as a filter
    void CreateSfcTunnel(GhostClient* client,
                         std::uint64_t terminal_value,
                         std::uint64_t service_value) {
      grpc::ClientContext context;
      CreateSfcRequest request;
      CreateSfcResponse response;
      GhostFilter* filter = GetFilter(&request);
      GhostTunnelIdentifier* tunnel_id = filter->mutable_tunnel_id();
      GhostLabel* terminal_label = tunnel_id->mutable_terminal_label();;
      GhostLabel* service_label = tunnel_id->mutable_service_label();
      terminal_label->set_value(terminal_value);
      service_label->set_value(service_value);
      client->CreateSfc(&context, request, &response);
    }
    // Creates Sfc using GhostRoutingIdentifier as a filter
    void CreateSfcRoute(GhostClient* client,
                         std::uint64_t value,
                         std::uint32_t prefix_len) {
      grpc::ClientContext context;
      CreateSfcRequest request;
      CreateSfcResponse response;
      GhostFilter* filter = GetFilter(&request);
      GhostRoutingIdentifier* routing_id = filter->mutable_routing_id();
      GhostLabelPrefix* dest_label_prefix = routing_id->mutable_destination_label_prefix();
      dest_label_prefix->set_value(value);
      dest_label_prefix->set_prefix_len(prefix_len);
      client->CreateSfc(&context, request, &response);
    }
    std::shared_ptr<grpc::ChannelCredentials> GetCreds(std::string key_file,
                                                       std::string key_cert,
                                                       std::string key_root) {
      std::string key = FileReader::ReadString(key_file);
      std::string cert = FileReader::ReadString(key_cert);
      std::string root = FileReader::ReadString(key_root);
      grpc::SslCredentialsOptions ssl_opts;
      ssl_opts.pem_root_certs = root;
      ssl_opts.pem_cert_chain = cert;
      ssl_opts.pem_private_key = key;
      return grpc::SslCredentials(ssl_opts);
    }
  }
}

int main(int argc, char** argv) {
  absl::ParseCommandLine(argc, argv);
  std::string server_address = absl::GetFlag(FLAGS_HOST) + ":" +
      std::to_string(absl::GetFlag(FLAGS_PORT));
  std::shared_ptr<grpc::ChannelCredentials> creds = grpc::InsecureChannelCredentials();
  usps_api_client::GhostClient client(
      grpc::CreateChannel(server_address, creds));
  return 0;
}
<|endoftext|>


<commit_before>/** \file    export_subsystem_ids_to_db.cc
 *  \brief   Export PPN's of records tagged as specific subsystems to the VuFind MySQL database
 *           to allow filtering
 *  \author  Johannes Riedl
 */

/*
    Copyright (C) 2018, Library of the University of Tübingen

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

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

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

#include <fstream>
#include <iostream>
#include <map>
#include <vector>
#include <cstdlib>
#include "Compiler.h"
#include "DbConnection.h"
#include "File.h"
#include "MARC.h"
#include "RegexMatcher.h"
#include "StringUtil.h"
#include "VuFind.h"
#include "util.h"

namespace {

enum Subsystem { RELBIB, BIBSTUDIES };
const std::vector<Subsystem> SUBSYSTEMS( { RELBIB, BIBSTUDIES } );

[[noreturn]] void Usage() {
    std::cerr << "Usage: " << ::progname << " [--input-format=(marc-21|marc-xml)] marc_input\n";
    std::exit(EXIT_FAILURE);
}

void InsertToDatabase(DbConnection * const db_connection, std::string * const insert_statement) {
    // Remove trailing comma and space:
    insert_statement->resize(insert_statement->size() - 2);
    *insert_statement += ';';
    db_connection->queryOrDie(*insert_statement);
}

std::string GetSubsystemTag(const Subsystem subsystem) {
    const std::string RELBIB_TAG("REL");
    const std::string BIBSTUDIES_TAG("BIB");
    switch (subsystem) {
    case  RELBIB:
      return RELBIB_TAG;
    case BIBSTUDIES:
      return BIBSTUDIES_TAG;
    }
    LOG_ERROR("Invalid Subsystem " + std::to_string(subsystem));
}

std::string GetSubsystemName(const Subsystem subsystem) {
    switch (subsystem) {
    case  RELBIB:
      return "relbib";
    case BIBSTUDIES:
      return "bibstudies";
    }
    LOG_ERROR("Invalid Subsystem " + std::to_string(subsystem));
}

void InsertIntoSql(DbConnection * const db_connection, const Subsystem subsystem, const std::set<std::string> &subsystem_record_ids) {
    if (subsystem_record_ids.empty())
        return;

    const std::string subsystem_id_table(GetSubsystemName(subsystem) + "_ids");
    db_connection->queryOrDie("TRUNCATE " + subsystem_id_table);

    const std::string INSERT_STATEMENT_START("INSERT INTO " + subsystem_id_table + "(record_id) VALUES");
    std::string insert_statement(INSERT_STATEMENT_START);
    size_t row_counter(0);
    const size_t MAX_ROW_COUNT(10000);

    for (const auto &record_id : subsystem_record_ids) {
        insert_statement += "('" + record_id + "'), ";
        if (++row_counter > MAX_ROW_COUNT) {
            InsertToDatabase(db_connection, &insert_statement);
            insert_statement = INSERT_STATEMENT_START;
            row_counter = 0;
        }

    }
    InsertToDatabase(db_connection, &insert_statement);
}

void ExtractIDsForSubsystems(MARC::Reader * const marc_reader, std::vector<std::set<std::string>> * const subsystem_ids) {
    while (const MARC::Record &record = marc_reader->read()) {
        for (const Subsystem subsystem : SUBSYSTEMS) {
            if (not record.getTagRange(GetSubsystemTag(subsystem)).empty())
                ((*subsystem_ids)[subsystem]).emplace(record.getControlNumber());
        }
    }
}

void InitSubsystemsIDsVector(std::vector<std::set<std::string>> * const subsystems_ids) {
    for (unsigned i = 0; i < SUBSYSTEMS.size(); ++i) {
        std::set<std::string> init_set;
        subsystems_ids->push_back(init_set);
    }
}

} // unnamed namespace

int main(int argc, char **argv) {
    ::progname = argv[0];

    if (argc != 2 and argc != 3)
        Usage();

    MARC::FileType reader_type(MARC::FileType::AUTO);
    if (argc == 3) {
        if (std::strcmp(argv[1], "--input-format=marc-21") == 0)
            reader_type = MARC::FileType::BINARY;
        else if (std::strcmp(argv[1], "--input-format=marc-xml") == 0)
            reader_type = MARC::FileType::XML;
        else
            Usage();
        ++argv, --argc;
    }

    const std::string marc_input_filename(argv[1]);
    unsigned int imported_count(0);

    try {
        std::string mysql_url;
        VuFind::GetMysqlURL(&mysql_url);
        DbConnection db_connection(mysql_url);

        std::unique_ptr<MARC::Reader> marc_reader(MARC::Reader::Factory(marc_input_filename, reader_type));
        std::vector<std::set<std::string>> subsystems_ids;
        InitSubsystemsIDsVector(&subsystems_ids);
        ExtractIDsForSubsystems(marc_reader.get(), &subsystems_ids);
        for (const auto subsystem : SUBSYSTEMS) {
            InsertIntoSql(&db_connection, subsystem, subsystems_ids[subsystem]);
            imported_count += subsystems_ids[subsystem].size();
        }

    } catch (const std::exception &x) {
        LOG_ERROR("caught exception: " + std::string(x.what()));
    }
    std::cerr << "Exported " << imported_count << " IDs to Database\n";
}

<commit_msg>Update export_subsystem_ids_to_db.cc<commit_after>/** \file    export_subsystem_ids_to_db.cc
 *  \brief   Export PPN's of records tagged as specific subsystems to the VuFind MySQL database
 *           to allow filtering
 *  \author  Johannes Riedl
 */

/*
    Copyright (C) 2018, Library of the University of Tübingen

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

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

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

#include <fstream>
#include <iostream>
#include <map>
#include <vector>
#include <cstdlib>
#include "Compiler.h"
#include "DbConnection.h"
#include "File.h"
#include "MARC.h"
#include "RegexMatcher.h"
#include "StringUtil.h"
#include "VuFind.h"
#include "util.h"

namespace {

enum Subsystem { RELBIB, BIBSTUDIES };
const std::vector<Subsystem> SUBSYSTEMS( { RELBIB, BIBSTUDIES } );

[[noreturn]] void Usage() {
    std::cerr << "Usage: " << ::progname << " [--input-format=(marc-21|marc-xml)] marc_input\n";
    std::exit(EXIT_FAILURE);
}

void InsertToDatabase(DbConnection * const db_connection, std::string * const insert_statement) {
    // Remove trailing comma and space:
    insert_statement->resize(insert_statement->size() - 2);
    *insert_statement += ';';
    db_connection->queryOrDie(*insert_statement);
}

std::string GetSubsystemTag(const Subsystem subsystem) {
    const std::string RELBIB_TAG("REL");
    const std::string BIBSTUDIES_TAG("BIB");
    switch (subsystem) {
    case  RELBIB:
      return RELBIB_TAG;
    case BIBSTUDIES:
      return BIBSTUDIES_TAG;
    }
    LOG_ERROR("Invalid Subsystem " + std::to_string(subsystem));
}

std::string GetSubsystemName(const Subsystem subsystem) {
    switch (subsystem) {
    case  RELBIB:
      return "relbib";
    case BIBSTUDIES:
      return "bibstudies";
    }
    LOG_ERROR("Invalid Subsystem " + std::to_string(subsystem));
}

void InsertIntoSql(DbConnection * const db_connection, const Subsystem subsystem, const std::set<std::string> &subsystem_record_ids) {
    if (subsystem_record_ids.empty())
        return;

    const std::string subsystem_id_table(GetSubsystemName(subsystem) + "_ids");
    db_connection->queryOrDie("TRUNCATE " + subsystem_id_table);

    const std::string INSERT_STATEMENT_START("INSERT INTO " + subsystem_id_table + "(record_id) VALUES");
    std::string insert_statement(INSERT_STATEMENT_START);
    size_t row_counter(0);
    const size_t MAX_ROW_COUNT(10000);

    for (const auto &record_id : subsystem_record_ids) {
        insert_statement += "('" + record_id + "'), ";
        if (++row_counter > MAX_ROW_COUNT) {
            InsertToDatabase(db_connection, &insert_statement);
            insert_statement = INSERT_STATEMENT_START;
            row_counter = 0;
        }

    }
    InsertToDatabase(db_connection, &insert_statement);
}

void ExtractIDsForSubsystems(MARC::Reader * const marc_reader, std::vector<std::set<std::string>> * const subsystem_ids) {
    while (const MARC::Record &record = marc_reader->read()) {
        for (const Subsystem subsystem : SUBSYSTEMS) {
            if (not record.getTagRange(GetSubsystemTag(subsystem)).empty())
                ((*subsystem_ids)[subsystem]).emplace(record.getControlNumber());
        }
    }
}

void InitSubsystemsIDsVector(std::vector<std::set<std::string>> * const subsystems_ids) {
    for (unsigned i = 0; i < SUBSYSTEMS.size(); ++i) {
        std::set<std::string> init_set;
        subsystems_ids->push_back(init_set);
    }
}

} // unnamed namespace

int main(int argc, char **argv) {
    ::progname = argv[0];

    if (argc != 2 and argc != 3)
        Usage();

    MARC::FileType reader_type(MARC::FileType::AUTO);
    if (argc == 3) {
        if (std::strcmp(argv[1], "--input-format=marc-21") == 0)
            reader_type = MARC::FileType::BINARY;
        else if (std::strcmp(argv[1], "--input-format=marc-xml") == 0)
            reader_type = MARC::FileType::XML;
        else
            Usage();
        ++argv, --argc;
    }

    const std::string marc_input_filename(argv[1]);
    unsigned imported_count(0);

    try {
        std::string mysql_url;
        VuFind::GetMysqlURL(&mysql_url);
        DbConnection db_connection(mysql_url);

        std::unique_ptr<MARC::Reader> marc_reader(MARC::Reader::Factory(marc_input_filename, reader_type));
        std::vector<std::set<std::string>> subsystems_ids;
        InitSubsystemsIDsVector(&subsystems_ids);
        ExtractIDsForSubsystems(marc_reader.get(), &subsystems_ids);
        for (const auto subsystem : SUBSYSTEMS) {
            InsertIntoSql(&db_connection, subsystem, subsystems_ids[subsystem]);
            imported_count += subsystems_ids[subsystem].size();
        }

    } catch (const std::exception &x) {
        LOG_ERROR("caught exception: " + std::string(x.what()));
    }
    std::cerr << "Exported " << imported_count << " IDs to Database\n";
}

<|endoftext|>