<commit_before>// Copyright (c) 2012 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.

#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/offline/offline_load_page.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "content/browser/tab_contents/interstitial_page.h"
#include "content/browser/tab_contents/test_tab_contents.h"
#include "content/test/test_browser_thread.h"

using content::BrowserThread;

static const char* kURL1 = "http://www.google.com/";
static const char* kURL2 = "http://www.gmail.com/";

namespace chromeos {

class OfflineLoadPageTest;

// An OfflineLoadPage class that does not create windows.
class TestOfflineLoadPage :  public chromeos::OfflineLoadPage {
 public:
  TestOfflineLoadPage(TabContents* tab_contents,
                      const GURL& url,
                      OfflineLoadPageTest* test_page)
    : chromeos::OfflineLoadPage(tab_contents, url, CompletionCallback()),
      test_page_(test_page) {
    interstitial_page_->DontCreateViewForTesting();
  }

  // chromeos::OfflineLoadPage override.
  virtual void NotifyBlockingPageComplete(bool proceed) OVERRIDE;

 private:
  OfflineLoadPageTest* test_page_;

  DISALLOW_COPY_AND_ASSIGN(TestOfflineLoadPage);
};

class OfflineLoadPageTest : public ChromeRenderViewHostTestHarness {
 public:
  // The decision the user made.
  enum UserResponse {
    PENDING,
    OK,
    CANCEL
  };

  OfflineLoadPageTest()
      : ui_thread_(BrowserThread::UI, MessageLoop::current()),
        io_thread_(BrowserThread::IO, MessageLoop::current()) {
  }

  virtual void SetUp() {
    ChromeRenderViewHostTestHarness::SetUp();
    user_response_ = PENDING;
  }

  void OnBlockingPageComplete(bool proceed) {
    if (proceed)
      user_response_ = OK;
    else
      user_response_ = CANCEL;
  }

  void Navigate(const char* url, int page_id) {
    contents()->TestDidNavigate(
        contents()->GetRenderViewHost(), page_id, GURL(url),
        content::PAGE_TRANSITION_TYPED);
  }

  void ShowInterstitial(const char* url) {
    new TestOfflineLoadPage(contents(), GURL(url), this);
  }

  // Returns the OfflineLoadPage currently showing or NULL if none is
  // showing.
  InterstitialPage* GetOfflineLoadPage() {
    return InterstitialPage::GetInterstitialPage(contents());
  }

  UserResponse user_response() const { return user_response_; }

 private:
  UserResponse user_response_;
  content::TestBrowserThread ui_thread_;
  content::TestBrowserThread io_thread_;

  // Initializes / shuts down a stub CrosLibrary.
  chromeos::ScopedStubCrosEnabler stub_cros_enabler_;

  DISALLOW_COPY_AND_ASSIGN(OfflineLoadPageTest);
};

void TestOfflineLoadPage::NotifyBlockingPageComplete(bool proceed) {
  test_page_->OnBlockingPageComplete(proceed);
}

TEST_F(OfflineLoadPageTest, OfflinePageProceed) {
  // Start a load.
  Navigate(kURL1, 1);
  // Load next page.
  controller().LoadURL(GURL(kURL2), content::Referrer(),
                       content::PAGE_TRANSITION_TYPED, std::string());

  // Simulate the load causing an offline browsing interstitial page
  // to be shown.
  ShowInterstitial(kURL2);
  InterstitialPage* interstitial = GetOfflineLoadPage();
  ASSERT_TRUE(interstitial);
  MessageLoop::current()->RunAllPending();

  // Simulate the user clicking "proceed".
  interstitial->Proceed();
  MessageLoop::current()->RunAllPending();

  EXPECT_EQ(OK, user_response());

  // The URL remains to be URL2.
  EXPECT_EQ(kURL2, contents()->GetURL().spec());

  // Commit navigation and the interstitial page is gone.
  Navigate(kURL2, 2);
  EXPECT_FALSE(GetOfflineLoadPage());
}

// Tests showing an offline page and not proceeding.
TEST_F(OfflineLoadPageTest, OfflinePageDontProceed) {
  // Start a load.
  Navigate(kURL1, 1);
  controller().LoadURL(GURL(kURL2), content::Referrer(),
                       content::PAGE_TRANSITION_TYPED, std::string());

  // Simulate the load causing an offline interstitial page to be shown.
  ShowInterstitial(kURL2);
  InterstitialPage* interstitial = GetOfflineLoadPage();
  ASSERT_TRUE(interstitial);
  MessageLoop::current()->RunAllPending();

  // Simulate the user clicking "don't proceed".
  interstitial->DontProceed();

  // The interstitial should be gone.
  EXPECT_EQ(CANCEL, user_response());
  EXPECT_FALSE(GetOfflineLoadPage());
  // We did not proceed, the pending entry should be gone.
  EXPECT_FALSE(controller().GetPendingEntry());
  // the URL is set back to kURL1.
  EXPECT_EQ(kURL1, contents()->GetURL().spec());
}

}  // namespace chromeos
<commit_msg>Disable crashing OfflineLoadPageTest<commit_after>// Copyright (c) 2012 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.

#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/offline/offline_load_page.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "content/browser/tab_contents/interstitial_page.h"
#include "content/browser/tab_contents/test_tab_contents.h"
#include "content/test/test_browser_thread.h"

using content::BrowserThread;

static const char* kURL1 = "http://www.google.com/";
static const char* kURL2 = "http://www.gmail.com/";

namespace chromeos {

class OfflineLoadPageTest;

// An OfflineLoadPage class that does not create windows.
class TestOfflineLoadPage :  public chromeos::OfflineLoadPage {
 public:
  TestOfflineLoadPage(TabContents* tab_contents,
                      const GURL& url,
                      OfflineLoadPageTest* test_page)
    : chromeos::OfflineLoadPage(tab_contents, url, CompletionCallback()),
      test_page_(test_page) {
    interstitial_page_->DontCreateViewForTesting();
  }

  // chromeos::OfflineLoadPage override.
  virtual void NotifyBlockingPageComplete(bool proceed) OVERRIDE;

 private:
  OfflineLoadPageTest* test_page_;

  DISALLOW_COPY_AND_ASSIGN(TestOfflineLoadPage);
};

class OfflineLoadPageTest : public ChromeRenderViewHostTestHarness {
 public:
  // The decision the user made.
  enum UserResponse {
    PENDING,
    OK,
    CANCEL
  };

  OfflineLoadPageTest()
      : ui_thread_(BrowserThread::UI, MessageLoop::current()),
        io_thread_(BrowserThread::IO, MessageLoop::current()) {
  }

  virtual void SetUp() {
    ChromeRenderViewHostTestHarness::SetUp();
    user_response_ = PENDING;
  }

  void OnBlockingPageComplete(bool proceed) {
    if (proceed)
      user_response_ = OK;
    else
      user_response_ = CANCEL;
  }

  void Navigate(const char* url, int page_id) {
    contents()->TestDidNavigate(
        contents()->GetRenderViewHost(), page_id, GURL(url),
        content::PAGE_TRANSITION_TYPED);
  }

  void ShowInterstitial(const char* url) {
    new TestOfflineLoadPage(contents(), GURL(url), this);
  }

  // Returns the OfflineLoadPage currently showing or NULL if none is
  // showing.
  InterstitialPage* GetOfflineLoadPage() {
    return InterstitialPage::GetInterstitialPage(contents());
  }

  UserResponse user_response() const { return user_response_; }

 private:
  UserResponse user_response_;
  content::TestBrowserThread ui_thread_;
  content::TestBrowserThread io_thread_;

  // Initializes / shuts down a stub CrosLibrary.
  chromeos::ScopedStubCrosEnabler stub_cros_enabler_;

  DISALLOW_COPY_AND_ASSIGN(OfflineLoadPageTest);
};

void TestOfflineLoadPage::NotifyBlockingPageComplete(bool proceed) {
  test_page_->OnBlockingPageComplete(proceed);
}

// Tests are disabled due to crash. see crbug.com/113219.
TEST_F(OfflineLoadPageTest, DISABLED_OfflinePageProceed) {
  // Start a load.
  Navigate(kURL1, 1);
  // Load next page.
  controller().LoadURL(GURL(kURL2), content::Referrer(),
                       content::PAGE_TRANSITION_TYPED, std::string());

  // Simulate the load causing an offline browsing interstitial page
  // to be shown.
  ShowInterstitial(kURL2);
  InterstitialPage* interstitial = GetOfflineLoadPage();
  ASSERT_TRUE(interstitial);
  MessageLoop::current()->RunAllPending();

  // Simulate the user clicking "proceed".
  interstitial->Proceed();
  MessageLoop::current()->RunAllPending();

  EXPECT_EQ(OK, user_response());

  // The URL remains to be URL2.
  EXPECT_EQ(kURL2, contents()->GetURL().spec());

  // Commit navigation and the interstitial page is gone.
  Navigate(kURL2, 2);
  EXPECT_FALSE(GetOfflineLoadPage());
}

// Tests showing an offline page and not proceeding.
TEST_F(OfflineLoadPageTest, DISABLED_OfflinePageDontProceed) {
  // Start a load.
  Navigate(kURL1, 1);
  controller().LoadURL(GURL(kURL2), content::Referrer(),
                       content::PAGE_TRANSITION_TYPED, std::string());

  // Simulate the load causing an offline interstitial page to be shown.
  ShowInterstitial(kURL2);
  InterstitialPage* interstitial = GetOfflineLoadPage();
  ASSERT_TRUE(interstitial);
  MessageLoop::current()->RunAllPending();

  // Simulate the user clicking "don't proceed".
  interstitial->DontProceed();

  // The interstitial should be gone.
  EXPECT_EQ(CANCEL, user_response());
  EXPECT_FALSE(GetOfflineLoadPage());
  // We did not proceed, the pending entry should be gone.
  EXPECT_FALSE(controller().GetPendingEntry());
  // the URL is set back to kURL1.
  EXPECT_EQ(kURL1, contents()->GetURL().spec());
}

}  // namespace chromeos
<|endoftext|>


<commit_before>// Copyright (c) 2014 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.

#include "chrome/browser/component_updater/sw_reporter_installer_win.h"

#include <stdint.h>
#include <string>
#include <vector>

#include "base/base_paths.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/metrics/sparse_histogram.h"
#include "base/path_service.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.h"
#include "base/process/kill.h"
#include "base/process/launch.h"
#include "base/task_runner_util.h"
#include "base/threading/worker_pool.h"
#include "base/time/time.h"
#include "base/win/registry.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/safe_browsing/srt_global_error_win.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/global_error/global_error_service.h"
#include "chrome/browser/ui/global_error/global_error_service_factory.h"
#include "chrome/common/pref_names.h"
#include "components/component_updater/component_updater_paths.h"
#include "components/component_updater/component_updater_service.h"
#include "components/component_updater/component_updater_utils.h"
#include "components/component_updater/default_component_installer.h"
#include "components/component_updater/pref_names.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "content/public/browser/browser_thread.h"

using content::BrowserThread;

namespace component_updater {

namespace {

// These values are used to send UMA information and are replicated in the
// histograms.xml file, so the order MUST NOT CHANGE.
enum SwReporterUmaValue {
  SW_REPORTER_EXPLICIT_REQUEST = 0,        // Deprecated.
  SW_REPORTER_STARTUP_RETRY = 1,           // Deprecated.
  SW_REPORTER_RETRIED_TOO_MANY_TIMES = 2,  // Deprecated.
  SW_REPORTER_START_EXECUTION = 3,
  SW_REPORTER_FAILED_TO_START = 4,
  SW_REPORTER_REGISTRY_EXIT_CODE = 5,
  SW_REPORTER_RESET_RETRIES = 6,  // Deprecated.
  SW_REPORTER_MAX,
};

// The maximum number of times to retry a download on startup.
const int kMaxRetry = 20;

// The number of days to wait before triggering another sw reporter run.
const int kDaysBetweenSwReporterRuns = 7;

// CRX hash. The extension id is: gkmgaooipdjhmangpemjhigmamcehddo. The hash was
// generated in Python with something like this:
// hashlib.sha256().update(open("<file>.crx").read()[16:16+294]).digest().
const uint8_t kSha256Hash[] = {0x6a, 0xc6, 0x0e, 0xe8, 0xf3, 0x97, 0xc0, 0xd6,
                               0xf4, 0xc9, 0x78, 0x6c, 0x0c, 0x24, 0x73, 0x3e,
                               0x05, 0xa5, 0x62, 0x4b, 0x2e, 0xc7, 0xb7, 0x1c,
                               0x5f, 0xea, 0xf0, 0x88, 0xf6, 0x97, 0x9b, 0xc7};

const base::FilePath::CharType kSwReporterExeName[] =
    FILE_PATH_LITERAL("software_reporter_tool.exe");

// Where to fetch the reporter exit code in the registry.
const wchar_t kSoftwareRemovalToolRegistryKey[] =
    L"Software\\Google\\Software Removal Tool";
const wchar_t kExitCodeRegistryValueName[] = L"ExitCode";

// Exit codes that identify that a cleanup is needed.
const int kCleanupNeeded = 0;
const int kPostRebootCleanupNeeded = 4;

void ReportUmaStep(SwReporterUmaValue value) {
  UMA_HISTOGRAM_ENUMERATION("SoftwareReporter.Step", value, SW_REPORTER_MAX);
}

void ReportUmaVersion(const base::Version& version) {
  DCHECK(!version.components().empty());
  UMA_HISTOGRAM_SPARSE_SLOWLY("SoftwareReporter.MinorVersion",
                              version.components().back());
  // The major version uses the 1st component value (when there is more than
  // one, since the last one is always the minor version) as a hi word in a
  // double word. The low word is either the second component (when there are
  // only three) or the 3rd one if there are at least 4. E.g., for W.X.Y.Z, we
  // ignore X, and Z is the minor version. We compute the major version with W
  // as the hi word, and Y as the low word. For X.Y.Z, we use X and Y as hi and
  // low words, and if we would have Y.Z we would use Y as the hi word and 0 as
  // the low word. major version is 0 if the version only has one component.
  uint32_t major_version = 0;
  if (version.components().size() > 1)
    major_version = 0x10000 * version.components()[0];
  if (version.components().size() < 4 && version.components().size() > 2)
    major_version += version.components()[1];
  else if (version.components().size() > 3)
    major_version += version.components()[2];
  UMA_HISTOGRAM_SPARSE_SLOWLY("SoftwareReporter.MajorVersion", major_version);
}

// This function is called on the UI thread to report the SwReporter exit code
// and then clear it from the registry as well as clear the execution state
// from the local state. This could be called from an interruptible worker
// thread so should be resilient to unexpected shutdown. |version| is provided
// so the kSwReporterPromptVersion prefs can be set.
void ReportAndClearExitCode(int exit_code, const std::string& version) {
  UMA_HISTOGRAM_SPARSE_SLOWLY("SoftwareReporter.ExitCode", exit_code);
  if (g_browser_process && g_browser_process->local_state()) {
    g_browser_process->local_state()->SetInteger(prefs::kSwReporterLastExitCode,
                                                 exit_code);
  }

  if (exit_code == kPostRebootCleanupNeeded || exit_code == kCleanupNeeded) {
    // Find the last active browser, which may be NULL, in which case we won't
    // show the prompt this time and will wait until the next run of the
    // reporter. We can't use other ways of finding a browser because we don't
    // have a profile.
    chrome::HostDesktopType desktop_type = chrome::GetActiveDesktop();
    Browser* browser = chrome::FindLastActiveWithHostDesktopType(desktop_type);
    if (browser) {
      Profile* profile = browser->profile();
      DCHECK(profile);
      // Now that we have a profile, make sure we have a tabbed browser since we
      // need to anchor the bubble to the toolbar's wrench menu. Create one if
      // none exist already.
      if (browser->type() != Browser::TYPE_TABBED) {
        browser = chrome::FindTabbedBrowser(profile, false, desktop_type);
        if (!browser)
          browser = new Browser(Browser::CreateParams(profile, desktop_type));
      }
      const std::string prompt_version =
          profile->GetPrefs()->GetString(prefs::kSwReporterPromptVersion);
      // Don't show the prompt again if it's been shown before.
      if (prompt_version.empty()) {
        profile->GetPrefs()->SetString(prefs::kSwReporterPromptVersion,
                                       version);
        profile->GetPrefs()->SetInteger(prefs::kSwReporterPromptReason,
                                        exit_code);
        GlobalErrorService* global_error_service =
            GlobalErrorServiceFactory::GetForProfile(profile);
        SRTGlobalError* global_error = new SRTGlobalError(global_error_service);
        // |global_error_service| takes ownership of |global_error| and keeps it
        // alive until RemoveGlobalError() is called, and even then, the object
        // is not destroyed, the caller of RemoveGlobalError is responsible to
        // destroy it, and in the case of the SRTGlobalError, it deletes itself
        // but only after the bubble has been interacted with.
        global_error_service->AddGlobalError(global_error);

        // Do not try to show bubble if another GlobalError is already showing
        // one. The bubble will be shown once the others have been dismissed.
        const GlobalErrorService::GlobalErrorList& global_errors(
            global_error_service->errors());
        GlobalErrorService::GlobalErrorList::const_iterator it;
        for (it = global_errors.begin(); it != global_errors.end(); ++it) {
          if ((*it)->GetBubbleView())
            break;
        }
        if (it == global_errors.end())
          global_error->ShowBubbleView(browser);
      }
    }
  }

  base::win::RegKey srt_key(
      HKEY_CURRENT_USER, kSoftwareRemovalToolRegistryKey, KEY_WRITE);
  srt_key.DeleteValue(kExitCodeRegistryValueName);
}

// This function is called from a worker thread to launch the SwReporter and
// wait for termination to collect its exit code. This task could be interrupted
// by a shutdown at anytime, so it shouldn't depend on anything external that
// could be shutdown beforehand.
void LaunchAndWaitForExit(const base::FilePath& exe_path,
                          const std::string& version) {
  const base::CommandLine reporter_command_line(exe_path);
  base::ProcessHandle scan_reporter_process = base::kNullProcessHandle;
  if (!base::LaunchProcess(reporter_command_line,
                           base::LaunchOptions(),
                           &scan_reporter_process)) {
    ReportUmaStep(SW_REPORTER_FAILED_TO_START);
    return;
  }
  ReportUmaStep(SW_REPORTER_START_EXECUTION);

  int exit_code = -1;
  bool success = base::WaitForExitCode(scan_reporter_process, &exit_code);
  DCHECK(success);
  base::CloseProcessHandle(scan_reporter_process);
  scan_reporter_process = base::kNullProcessHandle;
  // It's OK if this doesn't complete, the work will continue on next startup.
  BrowserThread::PostTask(
      BrowserThread::UI,
      FROM_HERE,
      base::Bind(&ReportAndClearExitCode, exit_code, version));
}

class SwReporterInstallerTraits : public ComponentInstallerTraits {
 public:
  explicit SwReporterInstallerTraits(PrefService* prefs) : prefs_(prefs) {}

  virtual ~SwReporterInstallerTraits() {}

  virtual bool VerifyInstallation(const base::FilePath& dir) const {
    return base::PathExists(dir.Append(kSwReporterExeName));
  }

  virtual bool CanAutoUpdate() const { return true; }

  virtual bool OnCustomInstall(const base::DictionaryValue& manifest,
                               const base::FilePath& install_dir) {
    return true;
  }

  virtual void ComponentReady(const base::Version& version,
                              const base::FilePath& install_dir,
                              scoped_ptr<base::DictionaryValue> manifest) {
    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    ReportUmaVersion(version);

    wcsncpy_s(version_dir_,
              _MAX_PATH,
              install_dir.value().c_str(),
              install_dir.value().size());

    // A previous run may have results in the registry, so check and report
    // them if present.
    std::string version_string(version.GetString());
    base::win::RegKey srt_key(
        HKEY_CURRENT_USER, kSoftwareRemovalToolRegistryKey, KEY_READ);
    DWORD exit_code;
    if (srt_key.Valid() &&
        srt_key.ReadValueDW(kExitCodeRegistryValueName, &exit_code) ==
            ERROR_SUCCESS) {
      ReportUmaStep(SW_REPORTER_REGISTRY_EXIT_CODE);
      ReportAndClearExitCode(exit_code, version_string);
    }

    // If we can't access local state, we can't see when we last ran, so
    // just exit without running.
    if (!g_browser_process || !g_browser_process->local_state())
      return;

    // Run the reporter if it hasn't been triggered in the
    // kDaysBetweenSwReporterRuns days.
    const base::Time last_time_triggered = base::Time::FromInternalValue(
        g_browser_process->local_state()->GetInt64(
            prefs::kSwReporterLastTimeTriggered));
    if ((base::Time::Now() - last_time_triggered).InDays() >=
        kDaysBetweenSwReporterRuns) {
      g_browser_process->local_state()->SetInt64(
          prefs::kSwReporterLastTimeTriggered,
          base::Time::Now().ToInternalValue());

      base::WorkerPool::PostTask(
          FROM_HERE,
          base::Bind(&LaunchAndWaitForExit,
                     install_dir.Append(kSwReporterExeName),
                     version_string),
          true);
    }
  }

  virtual base::FilePath GetBaseDirectory() const { return install_dir(); }

  virtual void GetHash(std::vector<uint8_t>* hash) const { GetPkHash(hash); }

  virtual std::string GetName() const { return "Software Reporter Tool"; }

  static base::FilePath install_dir() {
    // The base directory on windows looks like:
    // <profile>\AppData\Local\Google\Chrome\User Data\SwReporter\.
    base::FilePath result;
    PathService::Get(DIR_SW_REPORTER, &result);
    return result;
  }

  static std::string ID() {
    CrxComponent component;
    component.version = Version("0.0.0.0");
    GetPkHash(&component.pk_hash);
    return component_updater::GetCrxComponentID(component);
  }

  static base::FilePath VersionPath() { return base::FilePath(version_dir_); }

 private:
  static void GetPkHash(std::vector<uint8_t>* hash) {
    DCHECK(hash);
    hash->assign(kSha256Hash, kSha256Hash + sizeof(kSha256Hash));
  }

  PrefService* prefs_;
  static wchar_t version_dir_[_MAX_PATH];
};

wchar_t SwReporterInstallerTraits::version_dir_[] = {};

}  // namespace

void RegisterSwReporterComponent(ComponentUpdateService* cus,
                                 PrefService* prefs) {
  // Install the component.
  scoped_ptr<ComponentInstallerTraits> traits(
      new SwReporterInstallerTraits(prefs));
  // |cus| will take ownership of |installer| during installer->Register(cus).
  DefaultComponentInstaller* installer =
      new DefaultComponentInstaller(traits.Pass());
  installer->Register(cus);
}

void RegisterPrefsForSwReporter(PrefRegistrySimple* registry) {
  registry->RegisterInt64Pref(prefs::kSwReporterLastTimeTriggered, 0);
  registry->RegisterIntegerPref(prefs::kSwReporterLastExitCode, -1);
}

void RegisterProfilePrefsForSwReporter(
    user_prefs::PrefRegistrySyncable* registry) {
  registry->RegisterIntegerPref(
      prefs::kSwReporterPromptReason,
      -1,
      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);

  registry->RegisterStringPref(
      prefs::kSwReporterPromptVersion,
      "",
      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
}

}  // namespace component_updater
<commit_msg>Gate the SRTPrompt on a specific FieldTrial group.<commit_after>// Copyright (c) 2014 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.

#include "chrome/browser/component_updater/sw_reporter_installer_win.h"

#include <stdint.h>
#include <string>
#include <vector>

#include "base/base_paths.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/metrics/sparse_histogram.h"
#include "base/path_service.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.h"
#include "base/process/kill.h"
#include "base/process/launch.h"
#include "base/task_runner_util.h"
#include "base/threading/worker_pool.h"
#include "base/time/time.h"
#include "base/win/registry.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/safe_browsing/srt_global_error_win.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/global_error/global_error_service.h"
#include "chrome/browser/ui/global_error/global_error_service_factory.h"
#include "chrome/common/pref_names.h"
#include "components/component_updater/component_updater_paths.h"
#include "components/component_updater/component_updater_service.h"
#include "components/component_updater/component_updater_utils.h"
#include "components/component_updater/default_component_installer.h"
#include "components/component_updater/pref_names.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "content/public/browser/browser_thread.h"

using content::BrowserThread;

namespace component_updater {

namespace {

// These values are used to send UMA information and are replicated in the
// histograms.xml file, so the order MUST NOT CHANGE.
enum SwReporterUmaValue {
  SW_REPORTER_EXPLICIT_REQUEST = 0,        // Deprecated.
  SW_REPORTER_STARTUP_RETRY = 1,           // Deprecated.
  SW_REPORTER_RETRIED_TOO_MANY_TIMES = 2,  // Deprecated.
  SW_REPORTER_START_EXECUTION = 3,
  SW_REPORTER_FAILED_TO_START = 4,
  SW_REPORTER_REGISTRY_EXIT_CODE = 5,
  SW_REPORTER_RESET_RETRIES = 6,  // Deprecated.
  SW_REPORTER_MAX,
};

// The maximum number of times to retry a download on startup.
const int kMaxRetry = 20;

// The number of days to wait before triggering another sw reporter run.
const int kDaysBetweenSwReporterRuns = 7;

// CRX hash. The extension id is: gkmgaooipdjhmangpemjhigmamcehddo. The hash was
// generated in Python with something like this:
// hashlib.sha256().update(open("<file>.crx").read()[16:16+294]).digest().
const uint8_t kSha256Hash[] = {0x6a, 0xc6, 0x0e, 0xe8, 0xf3, 0x97, 0xc0, 0xd6,
                               0xf4, 0xc9, 0x78, 0x6c, 0x0c, 0x24, 0x73, 0x3e,
                               0x05, 0xa5, 0x62, 0x4b, 0x2e, 0xc7, 0xb7, 0x1c,
                               0x5f, 0xea, 0xf0, 0x88, 0xf6, 0x97, 0x9b, 0xc7};

const base::FilePath::CharType kSwReporterExeName[] =
    FILE_PATH_LITERAL("software_reporter_tool.exe");

// Where to fetch the reporter exit code in the registry.
const wchar_t kSoftwareRemovalToolRegistryKey[] =
    L"Software\\Google\\Software Removal Tool";
const wchar_t kExitCodeRegistryValueName[] = L"ExitCode";

// Field trial strings.
const char kSRTPromptTrialName[] = "SRTPromptFieldTrial";
const char kSRTPromptOnGroup[] = "On";

// Exit codes that identify that a cleanup is needed.
const int kCleanupNeeded = 0;
const int kPostRebootCleanupNeeded = 4;

void ReportUmaStep(SwReporterUmaValue value) {
  UMA_HISTOGRAM_ENUMERATION("SoftwareReporter.Step", value, SW_REPORTER_MAX);
}

void ReportUmaVersion(const base::Version& version) {
  DCHECK(!version.components().empty());
  UMA_HISTOGRAM_SPARSE_SLOWLY("SoftwareReporter.MinorVersion",
                              version.components().back());
  // The major version uses the 1st component value (when there is more than
  // one, since the last one is always the minor version) as a hi word in a
  // double word. The low word is either the second component (when there are
  // only three) or the 3rd one if there are at least 4. E.g., for W.X.Y.Z, we
  // ignore X, and Z is the minor version. We compute the major version with W
  // as the hi word, and Y as the low word. For X.Y.Z, we use X and Y as hi and
  // low words, and if we would have Y.Z we would use Y as the hi word and 0 as
  // the low word. major version is 0 if the version only has one component.
  uint32_t major_version = 0;
  if (version.components().size() > 1)
    major_version = 0x10000 * version.components()[0];
  if (version.components().size() < 4 && version.components().size() > 2)
    major_version += version.components()[1];
  else if (version.components().size() > 3)
    major_version += version.components()[2];
  UMA_HISTOGRAM_SPARSE_SLOWLY("SoftwareReporter.MajorVersion", major_version);
}

// This function is called on the UI thread to report the SwReporter exit code
// and then clear it from the registry as well as clear the execution state
// from the local state. This could be called from an interruptible worker
// thread so should be resilient to unexpected shutdown. |version| is provided
// so the kSwReporterPromptVersion prefs can be set.
void ReportAndClearExitCode(int exit_code, const std::string& version) {
  UMA_HISTOGRAM_SPARSE_SLOWLY("SoftwareReporter.ExitCode", exit_code);
  if (g_browser_process && g_browser_process->local_state()) {
    g_browser_process->local_state()->SetInteger(prefs::kSwReporterLastExitCode,
                                                 exit_code);
  }

  if ((exit_code == kPostRebootCleanupNeeded || exit_code == kCleanupNeeded) &&
      base::FieldTrialList::FindFullName(kSRTPromptTrialName) ==
          kSRTPromptOnGroup) {
    // Find the last active browser, which may be NULL, in which case we won't
    // show the prompt this time and will wait until the next run of the
    // reporter. We can't use other ways of finding a browser because we don't
    // have a profile.
    chrome::HostDesktopType desktop_type = chrome::GetActiveDesktop();
    Browser* browser = chrome::FindLastActiveWithHostDesktopType(desktop_type);
    if (browser) {
      Profile* profile = browser->profile();
      DCHECK(profile);
      // Now that we have a profile, make sure we have a tabbed browser since we
      // need to anchor the bubble to the toolbar's wrench menu. Create one if
      // none exist already.
      if (browser->type() != Browser::TYPE_TABBED) {
        browser = chrome::FindTabbedBrowser(profile, false, desktop_type);
        if (!browser)
          browser = new Browser(Browser::CreateParams(profile, desktop_type));
      }
      const std::string prompt_version =
          profile->GetPrefs()->GetString(prefs::kSwReporterPromptVersion);
      // Don't show the prompt again if it's been shown before.
      if (prompt_version.empty()) {
        profile->GetPrefs()->SetString(prefs::kSwReporterPromptVersion,
                                       version);
        profile->GetPrefs()->SetInteger(prefs::kSwReporterPromptReason,
                                        exit_code);
        GlobalErrorService* global_error_service =
            GlobalErrorServiceFactory::GetForProfile(profile);
        SRTGlobalError* global_error = new SRTGlobalError(global_error_service);
        // |global_error_service| takes ownership of |global_error| and keeps it
        // alive until RemoveGlobalError() is called, and even then, the object
        // is not destroyed, the caller of RemoveGlobalError is responsible to
        // destroy it, and in the case of the SRTGlobalError, it deletes itself
        // but only after the bubble has been interacted with.
        global_error_service->AddGlobalError(global_error);

        // Do not try to show bubble if another GlobalError is already showing
        // one. The bubble will be shown once the others have been dismissed.
        const GlobalErrorService::GlobalErrorList& global_errors(
            global_error_service->errors());
        GlobalErrorService::GlobalErrorList::const_iterator it;
        for (it = global_errors.begin(); it != global_errors.end(); ++it) {
          if ((*it)->GetBubbleView())
            break;
        }
        if (it == global_errors.end())
          global_error->ShowBubbleView(browser);
      }
    }
  }

  base::win::RegKey srt_key(
      HKEY_CURRENT_USER, kSoftwareRemovalToolRegistryKey, KEY_WRITE);
  srt_key.DeleteValue(kExitCodeRegistryValueName);
}

// This function is called from a worker thread to launch the SwReporter and
// wait for termination to collect its exit code. This task could be interrupted
// by a shutdown at anytime, so it shouldn't depend on anything external that
// could be shutdown beforehand.
void LaunchAndWaitForExit(const base::FilePath& exe_path,
                          const std::string& version) {
  const base::CommandLine reporter_command_line(exe_path);
  base::ProcessHandle scan_reporter_process = base::kNullProcessHandle;
  if (!base::LaunchProcess(reporter_command_line,
                           base::LaunchOptions(),
                           &scan_reporter_process)) {
    ReportUmaStep(SW_REPORTER_FAILED_TO_START);
    return;
  }
  ReportUmaStep(SW_REPORTER_START_EXECUTION);

  int exit_code = -1;
  bool success = base::WaitForExitCode(scan_reporter_process, &exit_code);
  DCHECK(success);
  base::CloseProcessHandle(scan_reporter_process);
  scan_reporter_process = base::kNullProcessHandle;
  // It's OK if this doesn't complete, the work will continue on next startup.
  BrowserThread::PostTask(
      BrowserThread::UI,
      FROM_HERE,
      base::Bind(&ReportAndClearExitCode, exit_code, version));
}

class SwReporterInstallerTraits : public ComponentInstallerTraits {
 public:
  explicit SwReporterInstallerTraits(PrefService* prefs) : prefs_(prefs) {}

  virtual ~SwReporterInstallerTraits() {}

  virtual bool VerifyInstallation(const base::FilePath& dir) const {
    return base::PathExists(dir.Append(kSwReporterExeName));
  }

  virtual bool CanAutoUpdate() const { return true; }

  virtual bool OnCustomInstall(const base::DictionaryValue& manifest,
                               const base::FilePath& install_dir) {
    return true;
  }

  virtual void ComponentReady(const base::Version& version,
                              const base::FilePath& install_dir,
                              scoped_ptr<base::DictionaryValue> manifest) {
    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    ReportUmaVersion(version);

    wcsncpy_s(version_dir_,
              _MAX_PATH,
              install_dir.value().c_str(),
              install_dir.value().size());

    // A previous run may have results in the registry, so check and report
    // them if present.
    std::string version_string(version.GetString());
    base::win::RegKey srt_key(
        HKEY_CURRENT_USER, kSoftwareRemovalToolRegistryKey, KEY_READ);
    DWORD exit_code;
    if (srt_key.Valid() &&
        srt_key.ReadValueDW(kExitCodeRegistryValueName, &exit_code) ==
            ERROR_SUCCESS) {
      ReportUmaStep(SW_REPORTER_REGISTRY_EXIT_CODE);
      ReportAndClearExitCode(exit_code, version_string);
    }

    // If we can't access local state, we can't see when we last ran, so
    // just exit without running.
    if (!g_browser_process || !g_browser_process->local_state())
      return;

    // Run the reporter if it hasn't been triggered in the
    // kDaysBetweenSwReporterRuns days.
    const base::Time last_time_triggered = base::Time::FromInternalValue(
        g_browser_process->local_state()->GetInt64(
            prefs::kSwReporterLastTimeTriggered));
    if ((base::Time::Now() - last_time_triggered).InDays() >=
        kDaysBetweenSwReporterRuns) {
      g_browser_process->local_state()->SetInt64(
          prefs::kSwReporterLastTimeTriggered,
          base::Time::Now().ToInternalValue());

      base::WorkerPool::PostTask(
          FROM_HERE,
          base::Bind(&LaunchAndWaitForExit,
                     install_dir.Append(kSwReporterExeName),
                     version_string),
          true);
    }
  }

  virtual base::FilePath GetBaseDirectory() const { return install_dir(); }

  virtual void GetHash(std::vector<uint8_t>* hash) const { GetPkHash(hash); }

  virtual std::string GetName() const { return "Software Reporter Tool"; }

  static base::FilePath install_dir() {
    // The base directory on windows looks like:
    // <profile>\AppData\Local\Google\Chrome\User Data\SwReporter\.
    base::FilePath result;
    PathService::Get(DIR_SW_REPORTER, &result);
    return result;
  }

  static std::string ID() {
    CrxComponent component;
    component.version = Version("0.0.0.0");
    GetPkHash(&component.pk_hash);
    return component_updater::GetCrxComponentID(component);
  }

  static base::FilePath VersionPath() { return base::FilePath(version_dir_); }

 private:
  static void GetPkHash(std::vector<uint8_t>* hash) {
    DCHECK(hash);
    hash->assign(kSha256Hash, kSha256Hash + sizeof(kSha256Hash));
  }

  PrefService* prefs_;
  static wchar_t version_dir_[_MAX_PATH];
};

wchar_t SwReporterInstallerTraits::version_dir_[] = {};

}  // namespace

void RegisterSwReporterComponent(ComponentUpdateService* cus,
                                 PrefService* prefs) {
  // The Sw reporter doesn't need to run if the user isn't reporting metrics and
  // isn't in the SRTPrompt field trial "On" group.
  if (!ChromeMetricsServiceAccessor::IsMetricsReportingEnabled() &&
      base::FieldTrialList::FindFullName(kSRTPromptTrialName) !=
          kSRTPromptOnGroup) {
    return;
  }

  // Install the component.
  scoped_ptr<ComponentInstallerTraits> traits(
      new SwReporterInstallerTraits(prefs));
  // |cus| will take ownership of |installer| during installer->Register(cus).
  DefaultComponentInstaller* installer =
      new DefaultComponentInstaller(traits.Pass());
  installer->Register(cus);
}

void RegisterPrefsForSwReporter(PrefRegistrySimple* registry) {
  registry->RegisterInt64Pref(prefs::kSwReporterLastTimeTriggered, 0);
  registry->RegisterIntegerPref(prefs::kSwReporterLastExitCode, -1);
}

void RegisterProfilePrefsForSwReporter(
    user_prefs::PrefRegistrySyncable* registry) {
  registry->RegisterIntegerPref(
      prefs::kSwReporterPromptReason,
      -1,
      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);

  registry->RegisterStringPref(
      prefs::kSwReporterPromptVersion,
      "",
      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
}

}  // namespace component_updater
<|endoftext|>


<commit_before>#include "Arith256.h"
#include "Runtime.h"
#include "Type.h"
#include "Endianness.h"

#include <llvm/IR/Function.h>
#include <gmp.h>

namespace dev
{
namespace eth
{
namespace jit
{

Arith256::Arith256(llvm::IRBuilder<>& _builder) :
	CompilerHelper(_builder)
{
	using namespace llvm;

	m_result = m_builder.CreateAlloca(Type::Word, nullptr, "arith.result");
	m_arg1 = m_builder.CreateAlloca(Type::Word, nullptr, "arith.arg1");
	m_arg2 = m_builder.CreateAlloca(Type::Word, nullptr, "arith.arg2");
	m_arg3 = m_builder.CreateAlloca(Type::Word, nullptr, "arith.arg3");

	using Linkage = GlobalValue::LinkageTypes;

	llvm::Type* arg2Types[] = {Type::WordPtr, Type::WordPtr, Type::WordPtr};
	llvm::Type* arg3Types[] = {Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr};

	m_mul = Function::Create(FunctionType::get(Type::Void, arg2Types, false), Linkage::ExternalLinkage, "arith_mul", getModule());
	m_div = Function::Create(FunctionType::get(Type::Void, arg3Types, false), Linkage::ExternalLinkage, "arith_div", getModule());
	m_sdiv = Function::Create(FunctionType::get(Type::Void, arg3Types, false), Linkage::ExternalLinkage, "arith_sdiv", getModule());
	m_exp = Function::Create(FunctionType::get(Type::Void, arg2Types, false), Linkage::ExternalLinkage, "arith_exp", getModule());
	m_addmod = Function::Create(FunctionType::get(Type::Void, arg3Types, false), Linkage::ExternalLinkage, "arith_addmod", getModule());
	m_mulmod = Function::Create(FunctionType::get(Type::Void, arg3Types, false), Linkage::ExternalLinkage, "arith_mulmod", getModule());
}

Arith256::~Arith256()
{}

llvm::Value* Arith256::binaryOp(llvm::Function* _op, llvm::Value* _arg1, llvm::Value* _arg2)
{
	m_builder.CreateStore(_arg1, m_arg1);
	m_builder.CreateStore(_arg2, m_arg2);
	m_builder.CreateCall3(_op, m_arg1, m_arg2, m_result);
	return m_builder.CreateLoad(m_result);
}

llvm::Value* Arith256::ternaryOp(llvm::Function* _op, llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3)
{
	m_builder.CreateStore(_arg1, m_arg1);
	m_builder.CreateStore(_arg2, m_arg2);
	m_builder.CreateStore(_arg3, m_arg3);
	m_builder.CreateCall4(_op, m_arg1, m_arg2, m_arg3, m_result);
	return m_builder.CreateLoad(m_result);
}

llvm::Value* Arith256::mul(llvm::Value* _arg1, llvm::Value* _arg2)
{
	return binaryOp(m_mul, _arg1, _arg2);
}

std::pair<llvm::Value*, llvm::Value*> Arith256::div(llvm::Value* _arg1, llvm::Value* _arg2)
{
	m_builder.CreateStore(_arg1, m_arg1);
	m_builder.CreateStore(_arg2, m_arg2);
	createCall(m_div, {m_arg1, m_arg2, m_arg3, m_result});
	return std::make_pair(m_builder.CreateLoad(m_arg3), m_builder.CreateLoad(m_result));
}

std::pair<llvm::Value*, llvm::Value*> Arith256::sdiv(llvm::Value* _arg1, llvm::Value* _arg2)
{
	m_builder.CreateStore(_arg1, m_arg1);
	m_builder.CreateStore(_arg2, m_arg2);
	createCall(m_sdiv, {m_arg1, m_arg2, m_arg3, m_result});
	return std::make_pair(m_builder.CreateLoad(m_arg3), m_builder.CreateLoad(m_result));
}

llvm::Value* Arith256::exp(llvm::Value* _arg1, llvm::Value* _arg2)
{
	return binaryOp(m_exp, _arg1, _arg2);
}

llvm::Value* Arith256::addmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3)
{
	return ternaryOp(m_addmod, _arg1, _arg2, _arg3);
}

llvm::Value* Arith256::mulmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3)
{
	return ternaryOp(m_mulmod, _arg1, _arg2, _arg3);
}

namespace
{
	using uint128 = __uint128_t;

//	uint128 add(uint128 a, uint128 b) { return a + b; }
//	uint128 mul(uint128 a, uint128 b) { return a * b; }
//
//	uint128 mulq(uint64_t x, uint64_t y)
//	{
//		return (uint128)x * (uint128)y;
//	}
//
//	uint128 addc(uint64_t x, uint64_t y)
//	{
//		return (uint128)x * (uint128)y;
//	}

	struct uint256
	{
		uint64_t lo;
		uint64_t mid;
		uint128 hi;
	};

//	uint256 add(uint256 x, uint256 y)
//	{
//		auto lo = (uint128) x.lo + y.lo;
//		auto mid = (uint128) x.mid + y.mid + (lo >> 64);
//		return {lo, mid, x.hi + y.hi + (mid >> 64)};
//	}

	uint256 mul(uint256 x, uint256 y)
	{
		auto t1 = (uint128) x.lo * y.lo;
		auto t2 = (uint128) x.lo * y.mid;
		auto t3 = x.lo * y.hi;
		auto t4 = (uint128) x.mid * y.lo;
		auto t5 = (uint128) x.mid * y.mid;
		auto t6 = x.mid * y.hi;
		auto t7 = x.hi * y.lo;
		auto t8 = x.hi * y.mid;

		auto lo = (uint64_t) t1;
		auto m1 = (t1 >> 64) + (uint64_t) t2;
		auto m2 = (uint64_t) m1;
		auto mid = (uint128) m2 + (uint64_t) t4;
		auto hi = (t2 >> 64) + t3 + (t4 >> 64) + t5 + (t6 << 64) + t7
			 + (t8 << 64) + (m1 >> 64) + (mid >> 64);

		return {lo, (uint64_t)mid, hi};
	}

	bool isZero(i256 const* _n)
	{
		return _n->a == 0 && _n->b == 0 && _n->c == 0 && _n->d == 0;
	}

	const auto nLimbs = sizeof(i256) / sizeof(mp_limb_t);

	// FIXME: Not thread-safe
	static mp_limb_t mod_limbs[] = {0, 0, 0, 0, 1};
	static_assert(sizeof(mod_limbs) / sizeof(mod_limbs[0]) == nLimbs + 1, "mp_limb_t size mismatch");
	static const mpz_t mod{nLimbs + 1, nLimbs + 1, &mod_limbs[0]};

	static mp_limb_t tmp_limbs[nLimbs + 2];
	static mpz_t tmp{nLimbs + 2, 0, &tmp_limbs[0]};

	int countLimbs(i256 const* _n)
	{
		static const auto limbsInWord = sizeof(_n->a) / sizeof(mp_limb_t);
		static_assert(limbsInWord == 1, "E?");

		int l = nLimbs;
		if (_n->d != 0) return l;
		l -= limbsInWord;
		if (_n->c != 0) return l;
		l -= limbsInWord;
		if (_n->b != 0) return l;
		l -= limbsInWord;
		if (_n->a != 0) return l;
		return 0;
	}

	void u2s(mpz_t _u)
	{
		if (static_cast<std::make_signed<mp_limb_t>::type>(_u->_mp_d[nLimbs - 1]) < 0)
		{
			mpz_sub(tmp, mod, _u);
			mpz_set(_u, tmp);
			_u->_mp_size = -_u->_mp_size;
		}
	}

	void s2u(mpz_t _s)
	{
		if (_s->_mp_size < 0)
		{
			mpz_add(tmp, mod, _s);
			mpz_set(_s, tmp);
		}
	}
}

}
}
}

extern "C"
{

	using namespace dev::eth::jit;

	EXPORT void arith_mul(uint256* _arg1, uint256* _arg2, uint256* o_result)
	{
		*o_result = mul(*_arg1, *_arg2);
	}

	EXPORT void arith_div(i256* _arg1, i256* _arg2, i256* o_div, i256* o_mod)
	{
		*o_div = {};
		*o_mod = {};
		if (isZero(_arg2))
			return;

		mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast<mp_limb_t*>(_arg1)};
		mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast<mp_limb_t*>(_arg2)};
		mpz_t q{nLimbs, 0, reinterpret_cast<mp_limb_t*>(o_div)};
		mpz_t r{nLimbs, 0, reinterpret_cast<mp_limb_t*>(o_mod)};

		mpz_tdiv_qr(q, r, x, y);
	}

	EXPORT void arith_sdiv(i256* _arg1, i256* _arg2, i256* o_div, i256* o_mod)
	{
		*o_div = {};
		*o_mod = {};
		if (isZero(_arg2))
			return;

		mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast<mp_limb_t*>(_arg1)};
		mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast<mp_limb_t*>(_arg2)};
		mpz_t q{nLimbs, 0, reinterpret_cast<mp_limb_t*>(o_div)};
		mpz_t r{nLimbs, 0, reinterpret_cast<mp_limb_t*>(o_mod)};
		u2s(x);
		u2s(y);
		mpz_tdiv_qr(q, r, x, y);
		s2u(q);
		s2u(r);
	}

	EXPORT void arith_exp(i256* _arg1, i256* _arg2, i256* o_result)
	{
		*o_result = {};

		static mp_limb_t mod_limbs[nLimbs + 1] = {};
		mod_limbs[nLimbs] = 1;
		static const mpz_t mod{nLimbs + 1, nLimbs + 1, &mod_limbs[0]};

		mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast<mp_limb_t*>(_arg1)};
		mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast<mp_limb_t*>(_arg2)};
		mpz_t z{nLimbs, 0, reinterpret_cast<mp_limb_t*>(o_result)};

		mpz_powm(z, x, y, mod);
	}

	EXPORT void arith_mulmod(i256* _arg1, i256* _arg2, i256* _arg3, i256* o_result)
	{
		*o_result = {};
		if (isZero(_arg3))
			return;

		mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast<mp_limb_t*>(_arg1)};
		mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast<mp_limb_t*>(_arg2)};
		mpz_t m{nLimbs, countLimbs(_arg3), reinterpret_cast<mp_limb_t*>(_arg3)};
		mpz_t z{nLimbs, 0, reinterpret_cast<mp_limb_t*>(o_result)};
		static mp_limb_t p_limbs[nLimbs * 2] = {};
		static mpz_t p{nLimbs * 2, 0, &p_limbs[0]};

		mpz_mul(p, x, y);
		mpz_tdiv_r(z, p, m);
	}

	EXPORT void arith_addmod(i256* _arg1, i256* _arg2, i256* _arg3, i256* o_result)
	{
		*o_result = {};
		if (isZero(_arg3))
			return;

		mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast<mp_limb_t*>(_arg1)};
		mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast<mp_limb_t*>(_arg2)};
		mpz_t m{nLimbs, countLimbs(_arg3), reinterpret_cast<mp_limb_t*>(_arg3)};
		mpz_t z{nLimbs, 0, reinterpret_cast<mp_limb_t*>(o_result)};
		static mp_limb_t s_limbs[nLimbs + 1] = {};
		static mpz_t s{nLimbs + 1, 0, &s_limbs[0]};

		mpz_add(s, x, y);
		mpz_tdiv_r(z, s, m);
	}

}

<commit_msg>Reimplementation of sdiv. Delegates work to div.<commit_after>#include "Arith256.h"
#include "Runtime.h"
#include "Type.h"
#include "Endianness.h"

#include <llvm/IR/Function.h>
#include <gmp.h>

namespace dev
{
namespace eth
{
namespace jit
{

Arith256::Arith256(llvm::IRBuilder<>& _builder) :
	CompilerHelper(_builder)
{
	using namespace llvm;

	m_result = m_builder.CreateAlloca(Type::Word, nullptr, "arith.result");
	m_arg1 = m_builder.CreateAlloca(Type::Word, nullptr, "arith.arg1");
	m_arg2 = m_builder.CreateAlloca(Type::Word, nullptr, "arith.arg2");
	m_arg3 = m_builder.CreateAlloca(Type::Word, nullptr, "arith.arg3");

	using Linkage = GlobalValue::LinkageTypes;

	llvm::Type* arg2Types[] = {Type::WordPtr, Type::WordPtr, Type::WordPtr};
	llvm::Type* arg3Types[] = {Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr};

	m_mul = Function::Create(FunctionType::get(Type::Void, arg2Types, false), Linkage::ExternalLinkage, "arith_mul", getModule());
	m_div = Function::Create(FunctionType::get(Type::Void, arg3Types, false), Linkage::ExternalLinkage, "arith_div", getModule());
	m_sdiv = Function::Create(FunctionType::get(Type::Void, arg3Types, false), Linkage::ExternalLinkage, "arith_sdiv", getModule());
	m_exp = Function::Create(FunctionType::get(Type::Void, arg2Types, false), Linkage::ExternalLinkage, "arith_exp", getModule());
	m_addmod = Function::Create(FunctionType::get(Type::Void, arg3Types, false), Linkage::ExternalLinkage, "arith_addmod", getModule());
	m_mulmod = Function::Create(FunctionType::get(Type::Void, arg3Types, false), Linkage::ExternalLinkage, "arith_mulmod", getModule());
}

Arith256::~Arith256()
{}

llvm::Value* Arith256::binaryOp(llvm::Function* _op, llvm::Value* _arg1, llvm::Value* _arg2)
{
	m_builder.CreateStore(_arg1, m_arg1);
	m_builder.CreateStore(_arg2, m_arg2);
	m_builder.CreateCall3(_op, m_arg1, m_arg2, m_result);
	return m_builder.CreateLoad(m_result);
}

llvm::Value* Arith256::ternaryOp(llvm::Function* _op, llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3)
{
	m_builder.CreateStore(_arg1, m_arg1);
	m_builder.CreateStore(_arg2, m_arg2);
	m_builder.CreateStore(_arg3, m_arg3);
	m_builder.CreateCall4(_op, m_arg1, m_arg2, m_arg3, m_result);
	return m_builder.CreateLoad(m_result);
}

llvm::Value* Arith256::mul(llvm::Value* _arg1, llvm::Value* _arg2)
{
	return binaryOp(m_mul, _arg1, _arg2);
}

std::pair<llvm::Value*, llvm::Value*> Arith256::div(llvm::Value* _arg1, llvm::Value* _arg2)
{
	m_builder.CreateStore(_arg1, m_arg1);
	m_builder.CreateStore(_arg2, m_arg2);
	createCall(m_div, {m_arg1, m_arg2, m_arg3, m_result});
	return std::make_pair(m_builder.CreateLoad(m_arg3), m_builder.CreateLoad(m_result));
}

std::pair<llvm::Value*, llvm::Value*> Arith256::sdiv(llvm::Value* _x, llvm::Value* _y)
{
	auto xIsNeg = m_builder.CreateICmpSLT(_x, Constant::get(0));
	auto xNeg = m_builder.CreateSub(Constant::get(0), _x);
	auto xAbs = m_builder.CreateSelect(xIsNeg, xNeg, _x);

	auto yIsNeg = m_builder.CreateICmpSLT(_y, Constant::get(0));
	auto yNeg = m_builder.CreateSub(Constant::get(0), _y);
	auto yAbs = m_builder.CreateSelect(yIsNeg, yNeg, _y);

	m_builder.CreateStore(xAbs, m_arg1);
	m_builder.CreateStore(yAbs, m_arg2);
	createCall(m_div, {m_arg1, m_arg2, m_arg3, m_result});
	auto qAbs = m_builder.CreateLoad(m_arg3);
	auto rAbs = m_builder.CreateLoad(m_result);

	// the reminder has the same sign as dividend
	auto rNeg = m_builder.CreateSub(Constant::get(0), rAbs);
	auto r = m_builder.CreateSelect(xIsNeg, rNeg, rAbs);

	auto qNeg = m_builder.CreateSub(Constant::get(0), qAbs);
	auto xyOpposite = m_builder.CreateXor(xIsNeg, yIsNeg);
	auto q = m_builder.CreateSelect(xyOpposite, qNeg, qAbs);

	return std::make_pair(q, r);
}

llvm::Value* Arith256::exp(llvm::Value* _arg1, llvm::Value* _arg2)
{
	return binaryOp(m_exp, _arg1, _arg2);
}

llvm::Value* Arith256::addmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3)
{
	return ternaryOp(m_addmod, _arg1, _arg2, _arg3);
}

llvm::Value* Arith256::mulmod(llvm::Value* _arg1, llvm::Value* _arg2, llvm::Value* _arg3)
{
	return ternaryOp(m_mulmod, _arg1, _arg2, _arg3);
}

namespace
{
	using uint128 = __uint128_t;

//	uint128 add(uint128 a, uint128 b) { return a + b; }
//	uint128 mul(uint128 a, uint128 b) { return a * b; }
//
//	uint128 mulq(uint64_t x, uint64_t y)
//	{
//		return (uint128)x * (uint128)y;
//	}
//
//	uint128 addc(uint64_t x, uint64_t y)
//	{
//		return (uint128)x * (uint128)y;
//	}

	struct uint256
	{
		uint64_t lo;
		uint64_t mid;
		uint128 hi;
	};

//	uint256 add(uint256 x, uint256 y)
//	{
//		auto lo = (uint128) x.lo + y.lo;
//		auto mid = (uint128) x.mid + y.mid + (lo >> 64);
//		return {lo, mid, x.hi + y.hi + (mid >> 64)};
//	}

	uint256 mul(uint256 x, uint256 y)
	{
		auto t1 = (uint128) x.lo * y.lo;
		auto t2 = (uint128) x.lo * y.mid;
		auto t3 = x.lo * y.hi;
		auto t4 = (uint128) x.mid * y.lo;
		auto t5 = (uint128) x.mid * y.mid;
		auto t6 = x.mid * y.hi;
		auto t7 = x.hi * y.lo;
		auto t8 = x.hi * y.mid;

		auto lo = (uint64_t) t1;
		auto m1 = (t1 >> 64) + (uint64_t) t2;
		auto m2 = (uint64_t) m1;
		auto mid = (uint128) m2 + (uint64_t) t4;
		auto hi = (t2 >> 64) + t3 + (t4 >> 64) + t5 + (t6 << 64) + t7
			 + (t8 << 64) + (m1 >> 64) + (mid >> 64);

		return {lo, (uint64_t)mid, hi};
	}

	bool isZero(i256 const* _n)
	{
		return _n->a == 0 && _n->b == 0 && _n->c == 0 && _n->d == 0;
	}

	const auto nLimbs = sizeof(i256) / sizeof(mp_limb_t);

	int countLimbs(i256 const* _n)
	{
		static const auto limbsInWord = sizeof(_n->a) / sizeof(mp_limb_t);
		static_assert(limbsInWord == 1, "E?");

		int l = nLimbs;
		if (_n->d != 0) return l;
		l -= limbsInWord;
		if (_n->c != 0) return l;
		l -= limbsInWord;
		if (_n->b != 0) return l;
		l -= limbsInWord;
		if (_n->a != 0) return l;
		return 0;
	}
}

}
}
}

extern "C"
{

	using namespace dev::eth::jit;

	EXPORT void arith_mul(uint256* _arg1, uint256* _arg2, uint256* o_result)
	{
		*o_result = mul(*_arg1, *_arg2);
	}

	EXPORT void arith_div(i256* _arg1, i256* _arg2, i256* o_div, i256* o_mod)
	{
		*o_div = {};
		*o_mod = {};
		if (isZero(_arg2))
			return;

		mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast<mp_limb_t*>(_arg1)};
		mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast<mp_limb_t*>(_arg2)};
		mpz_t q{nLimbs, 0, reinterpret_cast<mp_limb_t*>(o_div)};
		mpz_t r{nLimbs, 0, reinterpret_cast<mp_limb_t*>(o_mod)};

		mpz_tdiv_qr(q, r, x, y);
	}

	EXPORT void arith_exp(i256* _arg1, i256* _arg2, i256* o_result)
	{
		*o_result = {};

		static mp_limb_t mod_limbs[nLimbs + 1] = {};
		mod_limbs[nLimbs] = 1;
		static const mpz_t mod{nLimbs + 1, nLimbs + 1, &mod_limbs[0]};

		mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast<mp_limb_t*>(_arg1)};
		mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast<mp_limb_t*>(_arg2)};
		mpz_t z{nLimbs, 0, reinterpret_cast<mp_limb_t*>(o_result)};

		mpz_powm(z, x, y, mod);
	}

	EXPORT void arith_mulmod(i256* _arg1, i256* _arg2, i256* _arg3, i256* o_result)
	{
		*o_result = {};
		if (isZero(_arg3))
			return;

		mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast<mp_limb_t*>(_arg1)};
		mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast<mp_limb_t*>(_arg2)};
		mpz_t m{nLimbs, countLimbs(_arg3), reinterpret_cast<mp_limb_t*>(_arg3)};
		mpz_t z{nLimbs, 0, reinterpret_cast<mp_limb_t*>(o_result)};
		static mp_limb_t p_limbs[nLimbs * 2] = {};
		static mpz_t p{nLimbs * 2, 0, &p_limbs[0]};

		mpz_mul(p, x, y);
		mpz_tdiv_r(z, p, m);
	}

	EXPORT void arith_addmod(i256* _arg1, i256* _arg2, i256* _arg3, i256* o_result)
	{
		*o_result = {};
		if (isZero(_arg3))
			return;

		mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast<mp_limb_t*>(_arg1)};
		mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast<mp_limb_t*>(_arg2)};
		mpz_t m{nLimbs, countLimbs(_arg3), reinterpret_cast<mp_limb_t*>(_arg3)};
		mpz_t z{nLimbs, 0, reinterpret_cast<mp_limb_t*>(o_result)};
		static mp_limb_t s_limbs[nLimbs + 1] = {};
		static mpz_t s{nLimbs + 1, 0, &s_limbs[0]};

		mpz_add(s, x, y);
		mpz_tdiv_r(z, s, m);
	}

}

<|endoftext|>


<commit_before>// Copyright (c) 2012 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.

#include "chrome/browser/ui/webui/options/advanced_options_utils.h"

#include <windows.h>
#include <cryptuiapi.h>
#pragma comment(lib, "cryptui.lib")
#include <shellapi.h>

#include "base/bind.h"
#include "base/path_service.h"
#include "base/threading/thread.h"
#include "chrome/browser/browser_process.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"

using content::BrowserThread;
using content::WebContents;

namespace options {

// Callback that opens the Internet Options control panel dialog with the
// Connections tab selected.
void OpenConnectionDialogCallback() {
  // Using rundll32 seems better than LaunchConnectionDialog which causes a
  // new dialog to be made for each call.  rundll32 uses the same global
  // dialog and it seems to share with the shortcut in control panel.
  base::FilePath rundll32;
  PathService::Get(base::DIR_SYSTEM, &rundll32);
  rundll32 = rundll32.AppendASCII("rundll32.exe");

  base::FilePath shell32dll;
  PathService::Get(base::DIR_SYSTEM, &shell32dll);
  shell32dll = shell32dll.AppendASCII("shell32.dll");

  base::FilePath inetcpl;
  PathService::Get(base::DIR_SYSTEM, &inetcpl);
  inetcpl = inetcpl.AppendASCII("inetcpl.cpl,,4");

  std::wstring args(shell32dll.value());
  args.append(L",Control_RunDLL ");
  args.append(inetcpl.value());

  ShellExecute(NULL, L"open", rundll32.value().c_str(), args.c_str(), NULL,
               SW_SHOWNORMAL);
}

void AdvancedOptionsUtilities::ShowNetworkProxySettings(
      WebContents* web_contents) {
  DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::FILE));
  BrowserThread::PostTask(BrowserThread::FILE,
                          FROM_HERE,
                          base::Bind(&OpenConnectionDialogCallback));
}

void AdvancedOptionsUtilities::ShowManageSSLCertificates(
      WebContents* web_contents) {
  CRYPTUI_CERT_MGR_STRUCT cert_mgr = { 0 };
  cert_mgr.dwSize = sizeof(CRYPTUI_CERT_MGR_STRUCT);
  cert_mgr.hwndParent =
#if defined(USE_AURA)
      NULL;
#else
      web_contents->GetView()->GetTopLevelNativeWindow();
#endif
  ::CryptUIDlgCertMgr(&cert_mgr);
}

}  // namespace options
<commit_msg>Parent SSL certs window properly in win aura<commit_after>// Copyright (c) 2012 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.

#include "chrome/browser/ui/webui/options/advanced_options_utils.h"

#include <windows.h>
#include <cryptuiapi.h>
#pragma comment(lib, "cryptui.lib")
#include <shellapi.h>

#include "base/bind.h"
#include "base/path_service.h"
#include "base/threading/thread.h"
#include "chrome/browser/browser_process.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "ui/views/win/hwnd_util.h"

using content::BrowserThread;
using content::WebContents;

namespace options {

// Callback that opens the Internet Options control panel dialog with the
// Connections tab selected.
void OpenConnectionDialogCallback() {
  // Using rundll32 seems better than LaunchConnectionDialog which causes a
  // new dialog to be made for each call.  rundll32 uses the same global
  // dialog and it seems to share with the shortcut in control panel.
  base::FilePath rundll32;
  PathService::Get(base::DIR_SYSTEM, &rundll32);
  rundll32 = rundll32.AppendASCII("rundll32.exe");

  base::FilePath shell32dll;
  PathService::Get(base::DIR_SYSTEM, &shell32dll);
  shell32dll = shell32dll.AppendASCII("shell32.dll");

  base::FilePath inetcpl;
  PathService::Get(base::DIR_SYSTEM, &inetcpl);
  inetcpl = inetcpl.AppendASCII("inetcpl.cpl,,4");

  std::wstring args(shell32dll.value());
  args.append(L",Control_RunDLL ");
  args.append(inetcpl.value());

  ShellExecute(NULL, L"open", rundll32.value().c_str(), args.c_str(), NULL,
               SW_SHOWNORMAL);
}

void AdvancedOptionsUtilities::ShowNetworkProxySettings(
      WebContents* web_contents) {
  DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::FILE));
  BrowserThread::PostTask(BrowserThread::FILE,
                          FROM_HERE,
                          base::Bind(&OpenConnectionDialogCallback));
}

void AdvancedOptionsUtilities::ShowManageSSLCertificates(
      WebContents* web_contents) {
  CRYPTUI_CERT_MGR_STRUCT cert_mgr = { 0 };
  cert_mgr.dwSize = sizeof(CRYPTUI_CERT_MGR_STRUCT);
  cert_mgr.hwndParent = views::HWNDForNativeWindow(
      web_contents->GetView()->GetTopLevelNativeWindow());
  ::CryptUIDlgCertMgr(&cert_mgr);
}

}  // namespace options
<|endoftext|>


<commit_before>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2012 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#include "config.hpp"

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <pficommon/lang/cast.h>
#include "exception.hpp"
#include "jsonconfig.hpp"

using std::ifstream;
using std::string;
using std::stringstream;

namespace jubatus {
namespace common {

void config_fromlocal(const string& path, string& config) {
  ifstream ifc(path.c_str());
  if (!ifc) {
    throw JUBATUS_EXCEPTION(
        jubatus::exception::runtime_error("can't read " + path + " ."));
  }
  stringstream ss;
  ss << ifc.rdbuf();
  config = ss.str();
}

#ifdef HAVE_ZOOKEEPER_H
void config_fromzk(
    lock_service& z,
    const string& type,
    const string& name,
    string& config) {
  // server must get read lock for config_lock before call this method.
  string path;
  build_config_path(path, type, name);

  if (!z.exists(path)) {
    throw JUBATUS_EXCEPTION(
        jubatus::exception::runtime_error("config is not exists: " + path));
  }

  if (!z.read(path, config)) {
    throw JUBATUS_EXCEPTION(jubatus::exception::runtime_error(
          "failed to get config from zookeeper: " + path)
        << jubatus::exception::error_api_func("lock_service::read"));
  }

  LOG(INFO) << "get config from zookeeper: " << path;
}

void config_tozk(
    lock_service& z,
    const string& type,
    const string& name,
    string& config) {
  if (config == "") {
    throw JUBATUS_EXCEPTION(
        jubatus::exception::runtime_error("config is empty"));
  }

  try {
    pfi::lang::lexical_cast<pfi::text::json::json>(config);
  } catch (pfi::lang::parse_error& e) {
    string msg = std::string("cannot parse config to JSON: ") + e.what();
    throw JUBATUS_EXCEPTION(jubatus::exception::runtime_error(msg));
  }

  string lock_path;
  build_config_lock_path(lock_path, type, name);

  if (!z.exists(lock_path)) {
    throw JUBATUS_EXCEPTION(
        jubatus::exception::runtime_error("node is not exists: " + lock_path));
  }

  common::lock_service_mutex zk_config_lock(z, lock_path);
  int retry = 3;
  while (!zk_config_lock.try_lock()) {
    if (retry == 0) {
      throw JUBATUS_EXCEPTION(
          jubatus::exception::runtime_error("any user is using config?"));
    }
    retry--;
    sleep(1);
  }

  if (!is_no_workers(z, type, name)) {
    throw JUBATUS_EXCEPTION(jubatus::exception::runtime_error(
          "any server is running: " + type + ", " + name));
  }

  string path;
  build_config_path(path, type, name);

  bool success = true;
  success = z.create(path) && success;
  success = z.set(path, config) && success;

  if (!success) {
    throw JUBATUS_EXCEPTION(jubatus::exception::runtime_error(
          "failed to set config to zookeeper:" + path)
        << jubatus::exception::error_api_func("lock_service::set"));
  }

  LOG(INFO) << "set config to zookeeper: " << path;
}

void remove_config_fromzk(
    lock_service& z,
    const string& type,
    const string& name) {
  string lock_path;
  build_config_lock_path(lock_path, type, name);

  if (!z.exists(lock_path)) {
    throw JUBATUS_EXCEPTION(
        jubatus::exception::runtime_error("node is not exists: " + lock_path));
  }

  common::lock_service_mutex zk_config_lock(z, lock_path);
  int retry = 3;
  while (!zk_config_lock.try_lock()) {
    if (retry == 0) {
      throw JUBATUS_EXCEPTION(
          jubatus::exception::runtime_error("any user is using config?"));
    }
    retry--;
    sleep(1);
  }

  if (!is_no_workers(z, type, name)) {
    throw JUBATUS_EXCEPTION(jubatus::exception::runtime_error(
          "any server is running: " + type + ", " + name));
  }

  string path;
  build_config_path(path, type, name);

  if (!z.exists(path)) {
    throw JUBATUS_EXCEPTION(
        jubatus::exception::runtime_error("config is not exists: " + path));
  }

  if (!z.remove(path)) {
    throw JUBATUS_EXCEPTION(jubatus::exception::runtime_error(
          "failed to remove config from zookeeper:" + path)
        << jubatus::exception::error_api_func("lock_service::remove"));
  }

  LOG(INFO) << "remove config from zookeeper: " << path;
}

bool is_no_workers(lock_service& z, const string& type, const string& name) {
  std::vector<std::pair<std::string, int> > nodes;
  get_all_actors(z, type, name, nodes);
  if (nodes.empty()) {
    return true;
  } else {
    return false;
  }
}

#endif

}  // namespace common
}  // namespace jubatus
<commit_msg>fixed wrong include<commit_after>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2012 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#include "config.hpp"

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <pficommon/lang/cast.h>
#include <pficommon/text/json.h>
#include "exception.hpp"

using std::ifstream;
using std::string;
using std::stringstream;

namespace jubatus {
namespace common {

void config_fromlocal(const string& path, string& config) {
  ifstream ifc(path.c_str());
  if (!ifc) {
    throw JUBATUS_EXCEPTION(
        jubatus::exception::runtime_error("can't read " + path + " ."));
  }
  stringstream ss;
  ss << ifc.rdbuf();
  config = ss.str();
}

#ifdef HAVE_ZOOKEEPER_H
void config_fromzk(
    lock_service& z,
    const string& type,
    const string& name,
    string& config) {
  // server must get read lock for config_lock before call this method.
  string path;
  build_config_path(path, type, name);

  if (!z.exists(path)) {
    throw JUBATUS_EXCEPTION(
        jubatus::exception::runtime_error("config is not exists: " + path));
  }

  if (!z.read(path, config)) {
    throw JUBATUS_EXCEPTION(jubatus::exception::runtime_error(
          "failed to get config from zookeeper: " + path)
        << jubatus::exception::error_api_func("lock_service::read"));
  }

  LOG(INFO) << "get config from zookeeper: " << path;
}

void config_tozk(
    lock_service& z,
    const string& type,
    const string& name,
    string& config) {
  if (config == "") {
    throw JUBATUS_EXCEPTION(
        jubatus::exception::runtime_error("config is empty"));
  }

  try {
    pfi::lang::lexical_cast<pfi::text::json::json>(config);
  } catch (pfi::lang::parse_error& e) {
    string msg = std::string("cannot parse config to JSON: ") + e.what();
    throw JUBATUS_EXCEPTION(jubatus::exception::runtime_error(msg));
  }

  string lock_path;
  build_config_lock_path(lock_path, type, name);

  if (!z.exists(lock_path)) {
    throw JUBATUS_EXCEPTION(
        jubatus::exception::runtime_error("node is not exists: " + lock_path));
  }

  common::lock_service_mutex zk_config_lock(z, lock_path);
  int retry = 3;
  while (!zk_config_lock.try_lock()) {
    if (retry == 0) {
      throw JUBATUS_EXCEPTION(
          jubatus::exception::runtime_error("any user is using config?"));
    }
    retry--;
    sleep(1);
  }

  if (!is_no_workers(z, type, name)) {
    throw JUBATUS_EXCEPTION(jubatus::exception::runtime_error(
          "any server is running: " + type + ", " + name));
  }

  string path;
  build_config_path(path, type, name);

  bool success = true;
  success = z.create(path) && success;
  success = z.set(path, config) && success;

  if (!success) {
    throw JUBATUS_EXCEPTION(jubatus::exception::runtime_error(
          "failed to set config to zookeeper:" + path)
        << jubatus::exception::error_api_func("lock_service::set"));
  }

  LOG(INFO) << "set config to zookeeper: " << path;
}

void remove_config_fromzk(
    lock_service& z,
    const string& type,
    const string& name) {
  string lock_path;
  build_config_lock_path(lock_path, type, name);

  if (!z.exists(lock_path)) {
    throw JUBATUS_EXCEPTION(
        jubatus::exception::runtime_error("node is not exists: " + lock_path));
  }

  common::lock_service_mutex zk_config_lock(z, lock_path);
  int retry = 3;
  while (!zk_config_lock.try_lock()) {
    if (retry == 0) {
      throw JUBATUS_EXCEPTION(
          jubatus::exception::runtime_error("any user is using config?"));
    }
    retry--;
    sleep(1);
  }

  if (!is_no_workers(z, type, name)) {
    throw JUBATUS_EXCEPTION(jubatus::exception::runtime_error(
          "any server is running: " + type + ", " + name));
  }

  string path;
  build_config_path(path, type, name);

  if (!z.exists(path)) {
    throw JUBATUS_EXCEPTION(
        jubatus::exception::runtime_error("config is not exists: " + path));
  }

  if (!z.remove(path)) {
    throw JUBATUS_EXCEPTION(jubatus::exception::runtime_error(
          "failed to remove config from zookeeper:" + path)
        << jubatus::exception::error_api_func("lock_service::remove"));
  }

  LOG(INFO) << "remove config from zookeeper: " << path;
}

bool is_no_workers(lock_service& z, const string& type, const string& name) {
  std::vector<std::pair<std::string, int> > nodes;
  get_all_actors(z, type, name, nodes);
  if (nodes.empty()) {
    return true;
  } else {
    return false;
  }
}

#endif

}  // namespace common
}  // namespace jubatus
<|endoftext|>


<commit_before>#include <iostream>
#include <cmath>
#include "RandomNumberGenerator.h"
#include "Utils.h"
#include "Elliptical2D.h"

using namespace DNest3;
using namespace std;

Elliptical2D::Elliptical2D(double x_min, double x_max,
				double y_min, double y_max)
:x_min(x_min)
,x_max(x_max)
,y_min(y_min)
,y_max(y_max)
{
	if(x_min > x_max || y_min > y_max)
		cerr<<"# WARNING: Oddness in Elliptical2D constructor"<<endl;
	length_scale = sqrt((x_max - x_min)*
				(y_max - y_min));
}

void Elliptical2D::fromPrior()
{
	xc = x_min + (x_max - x_min)*randomU();
	yc = y_min + (y_max - y_min)*randomU();
	q = exp(log(0.2) + log(5./0.2)*randomU());
	theta = 2.*M_PI*randomU();
	cos_theta = cos(theta);
	sin_theta = sin(theta);

	mu_r = exp(log(0.01*length_scale) + log(100.)*randomU());
	beta_r = 2.*randomU();
}

void Elliptical2D::print(ostream& out) const
{
	out<<xc<<' '<<yc<<' ';
	out<<q<<' '<<theta<<' ';
	out<<mu_r<<' '<<beta_r<<' ';
}

double Elliptical2D::perturb_parameters()
{
	double logH = 0.;
	return logH;
}

double Elliptical2D::position_log_pdf(const vector<double>& position) const
{
	if(position[0] < x_min || position[0] > x_max
		|| position[1] < y_min || position[1] > y_max)
		return -1E300;
	return 0.;
}

void Elliptical2D::position_from_uniform(vector<double>& vec) const
{
	vec[0] = x_min + (x_max - x_min)*vec[0];
	vec[1] = y_min + (y_max - y_min)*vec[1];
}

void Elliptical2D::position_to_uniform(vector<double>& vec) const
{
	vec[0] = (vec[0] - x_min)/(x_max - x_min);
	vec[1] = (vec[1] - y_min)/(y_max - y_min);
}

<commit_msg>perturb_parameters()<commit_after>#include <iostream>
#include <cmath>
#include "RandomNumberGenerator.h"
#include "Utils.h"
#include "Elliptical2D.h"

using namespace DNest3;
using namespace std;

Elliptical2D::Elliptical2D(double x_min, double x_max,
				double y_min, double y_max)
:x_min(x_min)
,x_max(x_max)
,y_min(y_min)
,y_max(y_max)
{
	if(x_min > x_max || y_min > y_max)
		cerr<<"# WARNING: Oddness in Elliptical2D constructor"<<endl;
	length_scale = sqrt((x_max - x_min)*
				(y_max - y_min));
}

void Elliptical2D::fromPrior()
{
	xc = x_min + (x_max - x_min)*randomU();
	yc = y_min + (y_max - y_min)*randomU();
	q = exp(log(0.2) + log(5./0.2)*randomU());
	theta = 2.*M_PI*randomU();
	cos_theta = cos(theta);
	sin_theta = sin(theta);

	mu_r = exp(log(0.01*length_scale) + log(100.)*randomU());
	beta_r = 2.*randomU();
}

void Elliptical2D::print(ostream& out) const
{
	out<<xc<<' '<<yc<<' ';
	out<<q<<' '<<theta<<' ';
	out<<mu_r<<' '<<beta_r<<' ';
}

double Elliptical2D::perturb_parameters()
{
	double logH = 0.;

	double scale = pow(10., 1.5 - 6.*randomU());
	int which = randInt(5);
	if(which == 0)
	{
		xc += length_scale*scale*randn();
		yc += length_scale*scale*randn();
		xc = mod(xc - x_min, x_max - x_min) + x_min;
		yc = mod(yc - y_min, y_max - y_min) + y_min;
	}
	else if(which == 1)
	{
		q = log(q);
		q += log(5./0.2)*scale*randn();
		q = mod(q - log(0.2), log(5./0.2)) + log(0.2);
		q = exp(q);
	}
	else if(which == 2)
	{
		theta += 2.*M_PI*scale*randn();
		theta = mod(theta, 2.*M_PI);
		cos_theta = cos(theta);
		sin_theta = sin(theta);
	}
	else if(which == 3)
	{
		mu_r = log(mu_r);
		mu_r += log(100.)*scale*randn();
		mu_r = mod(mu_r - log(0.01*length_scale),
				log(100.)) + log(0.01*length_scale);
		mu_r = exp(mu_r);
	}
	else
	{
		beta_r += 2.*scale*randn();
		beta_r = mod(beta_r, 2.);
	}

	return logH;
}

double Elliptical2D::position_log_pdf(const vector<double>& position) const
{
	if(position[0] < x_min || position[0] > x_max
		|| position[1] < y_min || position[1] > y_max)
		return -1E300;
	return 0.;
}

void Elliptical2D::position_from_uniform(vector<double>& vec) const
{
	vec[0] = x_min + (x_max - x_min)*vec[0];
	vec[1] = y_min + (y_max - y_min)*vec[1];
}

void Elliptical2D::position_to_uniform(vector<double>& vec) const
{
	vec[0] = (vec[0] - x_min)/(x_max - x_min);
	vec[1] = (vec[1] - y_min)/(y_max - y_min);
}

<|endoftext|>


<commit_before>/** Copyright (C) 2017 European Spallation Source ERIC */

#include <gdgem/nmx/Readout.h>
#include <common/clustering/GapClusterer.h>
#include <common/clustering/GapMatcher.h>

#include <memory>
#include <stdio.h>
#include <unistd.h>
#include <test/TestBase.h>
#include <gdgem/NMXConfig.h>
#include <functional>

using namespace Gem;

static constexpr size_t min_cluster_size {3};

class HitSorter {
 public:
  HitSorter(SRSTime time, SRSMappings chips) :
      pTime(time), pChips(chips)
  {}

  void insert(const Readout &readout) {
    buffer.push_back(Hit());
    auto &e = buffer.back();
    e.plane = pChips.get_plane(readout);
    e.weight = readout.adc;
    e.coordinate = pChips.get_strip(readout);
    e.time = readout.srs_timestamp + static_cast<uint64_t>(readout.chiptime);
    if (readout.srs_timestamp < prev_srs_time)
      srs_overflows++;
    prev_srs_time = readout.srs_timestamp;
    if (readout.chiptime < 0)
      negative_chip_times++;
  }

  void flush() {
    std::sort(buffer.begin(), buffer.end(),
              [](const Hit &e1, const Hit &e2) {
                return e1.time < e2.time;
              });
    if (clusterer)
      clusterer->cluster(buffer);
    buffer.clear();
    if (clusterer)
      clusterer->flush();
  }

  std::shared_ptr<AbstractClusterer> clusterer;

  HitContainer buffer;
  uint64_t prev_srs_time {0};
  size_t srs_overflows{0};
  size_t negative_chip_times{0};

 private:
  SRSTime pTime;
  SRSMappings pChips;
};

class ReferenceDataTest : public TestBase {
protected:
  NMXConfig opts;
  std::string DataPath;
  std::vector<Readout> readouts;

  std::shared_ptr<HitSorter> sorter_x;
  std::shared_ptr<HitSorter> sorter_y;

  std::shared_ptr<AbstractMatcher> matcher;

  virtual void SetUp() {
    DataPath = TEST_DATA_PATH;
    opts = NMXConfig(DataPath + "/config.json", "");

    sorter_x =
        std::make_shared<HitSorter>(opts.time_config, opts.srs_mappings);
    sorter_y =
        std::make_shared<HitSorter>(opts.time_config, opts.srs_mappings);

    sorter_x->clusterer =
        std::make_shared<GapClusterer>(opts.clusterer_x.max_time_gap,
                                       opts.clusterer_x.max_strip_gap);
    sorter_y->clusterer =
        std::make_shared<GapClusterer>(opts.clusterer_y.max_time_gap,
                                       opts.clusterer_y.max_strip_gap);

    matcher = std::make_shared<GapMatcher>(
        opts.time_config.acquisition_window()*5,
        opts.matcher_max_delta_time);
  }

  virtual void TearDown() {
  }

  void add_readouts() {
    for (const auto& readout : readouts) {
      auto plane = opts.srs_mappings.get_plane(readout);
      EXPECT_LT(plane, 2) << "BAD PLANE"
                          << " fec:" << int(readout.fec)
                          << " chip:" << int(readout.chip_id) << "\n";

      if (plane == 0) {
        sorter_x->insert(readout);
      }
      if (plane == 1) {
        sorter_y->insert(readout);
      }
    }
  }

  void planes_test(size_t expected_x, size_t expected_y) {
    EXPECT_EQ(readouts.size(), expected_x + expected_y);
    EXPECT_EQ(sorter_x->buffer.size(), expected_x);
    EXPECT_EQ(sorter_y->buffer.size(), expected_y);
  }

  void test_plane(std::shared_ptr<AbstractClusterer> clusterer,
                  size_t expected_total,
                  size_t expected_filtered,
                  size_t min_cluster_size) {
    EXPECT_EQ(clusterer->stats_cluster_count, expected_total);
    size_t count_x{0};
    for (const auto& c : clusterer->clusters)
    {
//      MESSAGE() << c.debug(true) << "\n";
//      MESSAGE() << c.visualize(2) << "\n";
      if (c.hit_count() >= min_cluster_size)
        count_x++;
    }
    EXPECT_EQ(count_x, expected_filtered);
  }

};

TEST_F(ReferenceDataTest, PrintConfig) {
  MESSAGE() << "Test data config:\n" << opts.debug() << "\n";
}

TEST_F(ReferenceDataTest, a1) {
  ReadoutFile::read(DataPath + "/readouts/a00001", readouts);
  EXPECT_EQ(readouts.size(), 144);

  add_readouts();

  planes_test(144, 0);

  sorter_x->flush();
  sorter_y->flush();

  EXPECT_EQ(sorter_x->srs_overflows, 0);
  EXPECT_EQ(sorter_y->srs_overflows, 0);

  EXPECT_EQ(sorter_x->negative_chip_times, 0);
  EXPECT_EQ(sorter_y->negative_chip_times, 0);

  test_plane(sorter_x->clusterer, 22, 20, min_cluster_size);
  test_plane(sorter_y->clusterer, 0, 0, min_cluster_size);

  matcher->insert(0, sorter_x->clusterer->clusters);
  matcher->insert(1, sorter_y->clusterer->clusters);
  matcher->match(true);
  EXPECT_EQ(matcher->stats_event_count, 15);
  EXPECT_EQ(matcher->matched_events.size(), 15);
}

TEST_F(ReferenceDataTest, a10) {
  ReadoutFile::read(DataPath + "/readouts/a00010", readouts);
  EXPECT_EQ(readouts.size(), 920);

  add_readouts();

  planes_test(558, 362);

  sorter_x->flush();
  sorter_y->flush();

  EXPECT_EQ(sorter_x->srs_overflows, 0);
  EXPECT_EQ(sorter_y->srs_overflows, 0);

  EXPECT_EQ(sorter_x->negative_chip_times, 0);
  EXPECT_EQ(sorter_y->negative_chip_times, 0);

  test_plane(sorter_x->clusterer, 100, 96, min_cluster_size);
  test_plane(sorter_y->clusterer, 73, 68, min_cluster_size);

  matcher->insert(0, sorter_x->clusterer->clusters);
  matcher->insert(1, sorter_y->clusterer->clusters);
  matcher->match(true);
  EXPECT_EQ(matcher->stats_event_count, 101);
  EXPECT_EQ(matcher->matched_events.size(), 101);

//  for (const auto& e : matcher->matched_events) {
//    MESSAGE() << e.visualize(3) << "\n";
//  }
}

TEST_F(ReferenceDataTest, a100) {
  ReadoutFile::read(DataPath + "/readouts/a00100", readouts);
  EXPECT_EQ(readouts.size(), 126590);

  add_readouts();

  planes_test(84162, 42428);

  sorter_x->flush();
  sorter_y->flush();

  EXPECT_EQ(sorter_x->srs_overflows, 0);
  EXPECT_EQ(sorter_y->srs_overflows, 0);

  EXPECT_EQ(sorter_x->negative_chip_times, 12);
  EXPECT_EQ(sorter_y->negative_chip_times, 0);

  test_plane(sorter_x->clusterer, 19565, 19003, min_cluster_size);
  test_plane(sorter_y->clusterer, 10312, 9737, min_cluster_size);

  matcher->insert(0, sorter_x->clusterer->clusters);
  matcher->insert(1, sorter_y->clusterer->clusters);
  matcher->match(true);
  EXPECT_EQ(matcher->stats_event_count, 20224);
  EXPECT_EQ(matcher->matched_events.size(), 20224);
}

TEST_F(ReferenceDataTest, a1000) {
  ReadoutFile::read(DataPath + "/readouts/a01000", readouts);
  EXPECT_EQ(readouts.size(), 1416666);

  add_readouts();

  planes_test(934684, 481982);

  sorter_x->flush();
  sorter_y->flush();

  EXPECT_EQ(sorter_x->srs_overflows, 0);
  EXPECT_EQ(sorter_y->srs_overflows, 0);

  EXPECT_EQ(sorter_x->negative_chip_times, 59);
  EXPECT_EQ(sorter_y->negative_chip_times, 43);

  test_plane(sorter_x->clusterer, 217126, 211247, min_cluster_size);
  test_plane(sorter_y->clusterer, 116771, 109826, min_cluster_size);

  matcher->insert(0, sorter_x->clusterer->clusters);
  matcher->insert(1, sorter_y->clusterer->clusters);
  matcher->match(true);
  EXPECT_EQ(matcher->stats_event_count, 226492);
  EXPECT_EQ(matcher->matched_events.size(), 226492);
}

TEST_F(ReferenceDataTest, a10000) {
  ReadoutFile::read(DataPath + "/readouts/a10000", readouts);
  EXPECT_EQ(readouts.size(), 14293164);

  add_readouts();

  planes_test(9423281, 4869883);

  sorter_x->flush();
  sorter_y->flush();

  EXPECT_EQ(sorter_x->srs_overflows, 0);
  EXPECT_EQ(sorter_y->srs_overflows, 0);

  EXPECT_EQ(sorter_x->negative_chip_times, 665);
  EXPECT_EQ(sorter_y->negative_chip_times, 281);

  test_plane(sorter_x->clusterer, 2183659, 2125209, min_cluster_size);
  test_plane(sorter_y->clusterer, 1179939, 1111856, min_cluster_size);

  matcher->insert(0, sorter_x->clusterer->clusters);
  matcher->insert(1, sorter_y->clusterer->clusters);
  matcher->match(true);
  EXPECT_EQ(matcher->stats_event_count, 2285519);
  EXPECT_EQ(matcher->matched_events.size(), 2285519);
}

int main(int argc, char **argv) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>moved json file in reference data repo affected unit tests - this is not how it should be IMO<commit_after>/** Copyright (C) 2017 European Spallation Source ERIC */

#include <gdgem/nmx/Readout.h>
#include <common/clustering/GapClusterer.h>
#include <common/clustering/GapMatcher.h>

#include <memory>
#include <stdio.h>
#include <unistd.h>
#include <test/TestBase.h>
#include <gdgem/NMXConfig.h>
#include <functional>

using namespace Gem;

static constexpr size_t min_cluster_size {3};

class HitSorter {
 public:
  HitSorter(SRSTime time, SRSMappings chips) :
      pTime(time), pChips(chips)
  {}

  void insert(const Readout &readout) {
    buffer.push_back(Hit());
    auto &e = buffer.back();
    e.plane = pChips.get_plane(readout);
    e.weight = readout.adc;
    e.coordinate = pChips.get_strip(readout);
    e.time = readout.srs_timestamp + static_cast<uint64_t>(readout.chiptime);
    if (readout.srs_timestamp < prev_srs_time)
      srs_overflows++;
    prev_srs_time = readout.srs_timestamp;
    if (readout.chiptime < 0)
      negative_chip_times++;
  }

  void flush() {
    std::sort(buffer.begin(), buffer.end(),
              [](const Hit &e1, const Hit &e2) {
                return e1.time < e2.time;
              });
    if (clusterer)
      clusterer->cluster(buffer);
    buffer.clear();
    if (clusterer)
      clusterer->flush();
  }

  std::shared_ptr<AbstractClusterer> clusterer;

  HitContainer buffer;
  uint64_t prev_srs_time {0};
  size_t srs_overflows{0};
  size_t negative_chip_times{0};

 private:
  SRSTime pTime;
  SRSMappings pChips;
};

class ReferenceDataTest : public TestBase {
protected:
  NMXConfig opts;
  std::string DataPath;
  std::vector<Readout> readouts;

  std::shared_ptr<HitSorter> sorter_x;
  std::shared_ptr<HitSorter> sorter_y;

  std::shared_ptr<AbstractMatcher> matcher;

  virtual void SetUp() {
    DataPath = TEST_DATA_PATH;
    opts = NMXConfig(DataPath + "/readouts/config.json", "");

    sorter_x =
        std::make_shared<HitSorter>(opts.time_config, opts.srs_mappings);
    sorter_y =
        std::make_shared<HitSorter>(opts.time_config, opts.srs_mappings);

    sorter_x->clusterer =
        std::make_shared<GapClusterer>(opts.clusterer_x.max_time_gap,
                                       opts.clusterer_x.max_strip_gap);
    sorter_y->clusterer =
        std::make_shared<GapClusterer>(opts.clusterer_y.max_time_gap,
                                       opts.clusterer_y.max_strip_gap);

    matcher = std::make_shared<GapMatcher>(
        opts.time_config.acquisition_window()*5,
        opts.matcher_max_delta_time);
  }

  virtual void TearDown() {
  }

  void add_readouts() {
    for (const auto& readout : readouts) {
      auto plane = opts.srs_mappings.get_plane(readout);
      EXPECT_LT(plane, 2) << "BAD PLANE"
                          << " fec:" << int(readout.fec)
                          << " chip:" << int(readout.chip_id) << "\n";

      if (plane == 0) {
        sorter_x->insert(readout);
      }
      if (plane == 1) {
        sorter_y->insert(readout);
      }
    }
  }

  void planes_test(size_t expected_x, size_t expected_y) {
    EXPECT_EQ(readouts.size(), expected_x + expected_y);
    EXPECT_EQ(sorter_x->buffer.size(), expected_x);
    EXPECT_EQ(sorter_y->buffer.size(), expected_y);
  }

  void test_plane(std::shared_ptr<AbstractClusterer> clusterer,
                  size_t expected_total,
                  size_t expected_filtered,
                  size_t min_cluster_size) {
    EXPECT_EQ(clusterer->stats_cluster_count, expected_total);
    size_t count_x{0};
    for (const auto& c : clusterer->clusters)
    {
//      MESSAGE() << c.debug(true) << "\n";
//      MESSAGE() << c.visualize(2) << "\n";
      if (c.hit_count() >= min_cluster_size)
        count_x++;
    }
    EXPECT_EQ(count_x, expected_filtered);
  }

};

TEST_F(ReferenceDataTest, PrintConfig) {
  MESSAGE() << "Test data config:\n" << opts.debug() << "\n";
}

TEST_F(ReferenceDataTest, a1) {
  ReadoutFile::read(DataPath + "/readouts/a00001", readouts);
  EXPECT_EQ(readouts.size(), 144);

  add_readouts();

  planes_test(144, 0);

  sorter_x->flush();
  sorter_y->flush();

  EXPECT_EQ(sorter_x->srs_overflows, 0);
  EXPECT_EQ(sorter_y->srs_overflows, 0);

  EXPECT_EQ(sorter_x->negative_chip_times, 0);
  EXPECT_EQ(sorter_y->negative_chip_times, 0);

  test_plane(sorter_x->clusterer, 22, 20, min_cluster_size);
  test_plane(sorter_y->clusterer, 0, 0, min_cluster_size);

  matcher->insert(0, sorter_x->clusterer->clusters);
  matcher->insert(1, sorter_y->clusterer->clusters);
  matcher->match(true);
  EXPECT_EQ(matcher->stats_event_count, 15);
  EXPECT_EQ(matcher->matched_events.size(), 15);
}

TEST_F(ReferenceDataTest, a10) {
  ReadoutFile::read(DataPath + "/readouts/a00010", readouts);
  EXPECT_EQ(readouts.size(), 920);

  add_readouts();

  planes_test(558, 362);

  sorter_x->flush();
  sorter_y->flush();

  EXPECT_EQ(sorter_x->srs_overflows, 0);
  EXPECT_EQ(sorter_y->srs_overflows, 0);

  EXPECT_EQ(sorter_x->negative_chip_times, 0);
  EXPECT_EQ(sorter_y->negative_chip_times, 0);

  test_plane(sorter_x->clusterer, 100, 96, min_cluster_size);
  test_plane(sorter_y->clusterer, 73, 68, min_cluster_size);

  matcher->insert(0, sorter_x->clusterer->clusters);
  matcher->insert(1, sorter_y->clusterer->clusters);
  matcher->match(true);
  EXPECT_EQ(matcher->stats_event_count, 101);
  EXPECT_EQ(matcher->matched_events.size(), 101);

//  for (const auto& e : matcher->matched_events) {
//    MESSAGE() << e.visualize(3) << "\n";
//  }
}

TEST_F(ReferenceDataTest, a100) {
  ReadoutFile::read(DataPath + "/readouts/a00100", readouts);
  EXPECT_EQ(readouts.size(), 126590);

  add_readouts();

  planes_test(84162, 42428);

  sorter_x->flush();
  sorter_y->flush();

  EXPECT_EQ(sorter_x->srs_overflows, 0);
  EXPECT_EQ(sorter_y->srs_overflows, 0);

  EXPECT_EQ(sorter_x->negative_chip_times, 12);
  EXPECT_EQ(sorter_y->negative_chip_times, 0);

  test_plane(sorter_x->clusterer, 19565, 19003, min_cluster_size);
  test_plane(sorter_y->clusterer, 10312, 9737, min_cluster_size);

  matcher->insert(0, sorter_x->clusterer->clusters);
  matcher->insert(1, sorter_y->clusterer->clusters);
  matcher->match(true);
  EXPECT_EQ(matcher->stats_event_count, 20224);
  EXPECT_EQ(matcher->matched_events.size(), 20224);
}

TEST_F(ReferenceDataTest, a1000) {
  ReadoutFile::read(DataPath + "/readouts/a01000", readouts);
  EXPECT_EQ(readouts.size(), 1416666);

  add_readouts();

  planes_test(934684, 481982);

  sorter_x->flush();
  sorter_y->flush();

  EXPECT_EQ(sorter_x->srs_overflows, 0);
  EXPECT_EQ(sorter_y->srs_overflows, 0);

  EXPECT_EQ(sorter_x->negative_chip_times, 59);
  EXPECT_EQ(sorter_y->negative_chip_times, 43);

  test_plane(sorter_x->clusterer, 217126, 211247, min_cluster_size);
  test_plane(sorter_y->clusterer, 116771, 109826, min_cluster_size);

  matcher->insert(0, sorter_x->clusterer->clusters);
  matcher->insert(1, sorter_y->clusterer->clusters);
  matcher->match(true);
  EXPECT_EQ(matcher->stats_event_count, 226492);
  EXPECT_EQ(matcher->matched_events.size(), 226492);
}

TEST_F(ReferenceDataTest, a10000) {
  ReadoutFile::read(DataPath + "/readouts/a10000", readouts);
  EXPECT_EQ(readouts.size(), 14293164);

  add_readouts();

  planes_test(9423281, 4869883);

  sorter_x->flush();
  sorter_y->flush();

  EXPECT_EQ(sorter_x->srs_overflows, 0);
  EXPECT_EQ(sorter_y->srs_overflows, 0);

  EXPECT_EQ(sorter_x->negative_chip_times, 665);
  EXPECT_EQ(sorter_y->negative_chip_times, 281);

  test_plane(sorter_x->clusterer, 2183659, 2125209, min_cluster_size);
  test_plane(sorter_y->clusterer, 1179939, 1111856, min_cluster_size);

  matcher->insert(0, sorter_x->clusterer->clusters);
  matcher->insert(1, sorter_y->clusterer->clusters);
  matcher->match(true);
  EXPECT_EQ(matcher->stats_event_count, 2285519);
  EXPECT_EQ(matcher->matched_events.size(), 2285519);
}

int main(int argc, char **argv) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/**
 * @file   ExperimentBBO.hpp
 * @brief  ExperimentBBO class header file.
 * @author Freek Stulp
 *
 * This file is part of DmpBbo, a set of libraries and programs for the
 * black-box optimization of dynamical movement primitives.
 * Copyright (C) 2014 Freek Stulp, ENSTA-ParisTech
 *
 * DmpBbo is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * DmpBbo is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with DmpBbo.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef EXPERIMENTBBO_H
#define EXPERIMENTBBO_H

#include <vector>
#include <eigen3/Eigen/Core>

namespace DmpBbo {

class Task;
class TaskSolver;
class DistributionGaussian;
class Updater;

/** POD class to store all objects relevant to running and evolutionary optimization. */
class ExperimentBBO
{

public:

  /** Constructor.
   * \param[in] task_arg The Task to optimize
   * \param[in] task_solver_arg The TaskSolver that will solve the task
   * \param[in] initial_distribution_arg The initial parameter distribution
   * \param[in] updater_arg The Updater used to update the parameters
   * \param[in] n_updates_arg The number of updates to perform
   * \param[in] n_samples_per_update_arg The number of samples per update
   */
  ExperimentBBO(
    Task* task_arg,
    TaskSolver* task_solver_arg,
    DistributionGaussian* initial_distribution_arg,
    Updater* updater_arg,
    int n_updates_arg,
    int n_samples_per_update_arg
  );

  /** Task to be used during evaluation.
   */
   Task* task;

  /** Task solver to be used for a rollout.
   */
   TaskSolver* task_solver;

  /** The initial parameter distribution for the search. */
   DistributionGaussian*  initial_distribution;

  /** The updater used to update the parameters of the distribution. */
   Updater* updater;

  /** The number of updates to perform. */
  int n_updates;

  /** The number of samples per update. */
  int n_samples_per_update;

};

}

/*
class ExperimentBBOResults
{
  ExperimentBBO experiment;
  vector<UpdateSummary> update_summaries;
  vector<vector<MatrixXd>> cost_vars;
}
*/

#endif
<commit_msg>Made members const (possible now because serialization disabled)<commit_after>/**
 * @file   ExperimentBBO.hpp
 * @brief  ExperimentBBO class header file.
 * @author Freek Stulp
 *
 * This file is part of DmpBbo, a set of libraries and programs for the
 * black-box optimization of dynamical movement primitives.
 * Copyright (C) 2014 Freek Stulp, ENSTA-ParisTech
 *
 * DmpBbo is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * DmpBbo is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with DmpBbo.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef EXPERIMENTBBO_H
#define EXPERIMENTBBO_H

#include <vector>
#include <eigen3/Eigen/Core>

namespace DmpBbo {

class Task;
class TaskSolver;
class DistributionGaussian;
class Updater;

/** POD class to store all objects relevant to running and evolutionary optimization. */
class ExperimentBBO
{

public:

  /** Constructor.
   * \param[in] task_arg The Task to optimize
   * \param[in] task_solver_arg The TaskSolver that will solve the task
   * \param[in] initial_distribution_arg The initial parameter distribution
   * \param[in] updater_arg The Updater used to update the parameters
   * \param[in] n_updates_arg The number of updates to perform
   * \param[in] n_samples_per_update_arg The number of samples per update
   */
  ExperimentBBO(
    Task* task_arg,
    TaskSolver* task_solver_arg,
    DistributionGaussian* initial_distribution_arg,
    Updater* updater_arg,
    int n_updates_arg,
    int n_samples_per_update_arg
  );

  /** Task to be used during evaluation.
   */
  const Task* task;

  /** Task solver to be used for a rollout.
   */
  const TaskSolver* task_solver;

  /** The initial parameter distribution for the search. */
  const DistributionGaussian*  initial_distribution;

  /** The updater used to update the parameters of the distribution. */
  const Updater* updater;

  /** The number of updates to perform. */
  const int n_updates;

  /** The number of samples per update. */
  const int n_samples_per_update;

};

}

/*
class ExperimentBBOResults
{
  ExperimentBBO experiment;
  vector<UpdateSummary> update_summaries;
  vector<vector<MatrixXd>> cost_vars;
}
*/

#endif
<|endoftext|>