<commit_before>// Copyright (c) 2006-2008 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 "base/file_util.h"
#include "base/path_service.h"
#include "base/platform_thread.h"
#include "base/string_util.h"
#include "base/test/test_file_util.h"
#include "base/time.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"

using base::TimeDelta;
using base::TimeTicks;

namespace {

class StartupTest : public UITest {
 public:
  StartupTest() {
    show_window_ = true;
    pages_ = "about:blank";
  }
  void SetUp() {}
  void TearDown() {}

  // Load a file on startup rather than about:blank.  This tests a longer
  // startup path, including resource loading and the loading of gears.dll.
  void SetUpWithFileURL() {
    FilePath file_url;
    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &file_url));
    file_url = file_url.AppendASCII("simple.html");
    ASSERT_TRUE(file_util::PathExists(file_url));
    launch_arguments_.AppendLooseValue(file_url.ToWStringHack());

    pages_ = WideToUTF8(file_url.ToWStringHack());
  }

  // Use the given profile in the test data extensions/profiles dir.  This tests
  // startup with extensions installed.
  void SetUpWithExtensionsProfile(const char* profile) {
    FilePath data_dir;
    PathService::Get(chrome::DIR_TEST_DATA, &data_dir);
    data_dir = data_dir.AppendASCII("extensions").AppendASCII("profiles").
        AppendASCII(profile);
    set_template_user_data(data_dir);

    // For now, these tests still depend on toolstrips.
    launch_arguments_.AppendSwitch(switches::kEnableExtensionToolstrips);
  }

  void RunStartupTest(const char* graph, const char* trace,
      bool test_cold, bool important, UITest::ProfileType profile_type) {
    profile_type_ = profile_type;

    // Sets the profile data for the run.  For now, this is only used for
    // the non-default themes test.
    if (profile_type != UITest::DEFAULT_THEME) {
      set_template_user_data(UITest::ComputeTypicalUserDataSource(
          profile_type));
    }

    const int kNumCyclesMax = 20;
    int numCycles = kNumCyclesMax;
// It's ok for unit test code to use getenv(), isn't it?
#if defined(OS_WIN)
#pragma warning( disable : 4996 )
#endif
    const char* numCyclesEnv = getenv("STARTUP_TESTS_NUMCYCLES");
    if (numCyclesEnv && StringToInt(numCyclesEnv, &numCycles))
      LOG(INFO) << "STARTUP_TESTS_NUMCYCLES set in environment, "
                << "so setting numCycles to " << numCycles;

    TimeDelta timings[kNumCyclesMax];
    for (int i = 0; i < numCycles; ++i) {
      if (test_cold) {
        FilePath dir_app;
        ASSERT_TRUE(PathService::Get(chrome::DIR_APP, &dir_app));

        FilePath chrome_exe(dir_app.Append(
            FilePath::FromWStringHack(chrome::kBrowserProcessExecutablePath)));
        ASSERT_TRUE(EvictFileFromSystemCacheWrapper(chrome_exe));
#if defined(OS_WIN)
        // chrome.dll is windows specific.
        FilePath chrome_dll(dir_app.Append(FILE_PATH_LITERAL("chrome.dll")));
        ASSERT_TRUE(EvictFileFromSystemCacheWrapper(chrome_dll));
#endif

#if defined(OS_WIN)
        // TODO(port): Re-enable once gears is working on mac/linux.
        FilePath gears_dll;
        ASSERT_TRUE(PathService::Get(chrome::FILE_GEARS_PLUGIN, &gears_dll));
        ASSERT_TRUE(EvictFileFromSystemCacheWrapper(gears_dll));
#else
        NOTIMPLEMENTED() << "gears not enabled yet";
#endif
      }
      UITest::SetUp();
      TimeTicks end_time = TimeTicks::Now();
      timings[i] = end_time - browser_launch_time_;
      // TODO(beng): Can't shut down so quickly. Figure out why, and fix. If we
      // do, we crash.
      PlatformThread::Sleep(50);
      UITest::TearDown();

      if (i == 0) {
        // Re-use the profile data after first run so that the noise from
        // creating databases doesn't impact all the runs.
        clear_profile_ = false;
        // Clear template_user_data_ so we don't try to copy it over each time
        // through.
        set_template_user_data(FilePath());
      }
    }

    std::string times;
    for (int i = 0; i < numCycles; ++i)
      StringAppendF(&times, "%.2f,", timings[i].InMillisecondsF());
    PrintResultList(graph, "", trace, times, "ms", important);
  }

 protected:
  std::string pages_;
};

class StartupReferenceTest : public StartupTest {
 public:
  // override the browser directory that is used by UITest::SetUp to cause it
  // to use the reference build instead.
  void SetUp() {
    FilePath dir;
    PathService::Get(chrome::DIR_TEST_TOOLS, &dir);
    dir = dir.AppendASCII("reference_build");
#if defined(OS_WIN)
    dir = dir.AppendASCII("chrome");
#elif defined(OS_LINUX)
    dir = dir.AppendASCII("chrome_linux");
#elif defined(OS_MACOSX)
    dir = dir.AppendASCII("chrome_mac");
#endif
    browser_directory_ = dir;
  }
};

TEST_F(StartupTest, Perf) {
  RunStartupTest("warm", "t", false /* not cold */, true /* important */,
                 UITest::DEFAULT_THEME);
}

TEST_F(StartupReferenceTest, Perf) {
  RunStartupTest("warm", "t_ref", false /* not cold */,
                 true /* important */, UITest::DEFAULT_THEME);
}

// TODO(mpcomplete): Should we have reference timings for all these?

TEST_F(StartupTest, PerfCold) {
  RunStartupTest("cold", "t", true /* cold */, false /* not important */,
                 UITest::DEFAULT_THEME);
}

TEST_F(StartupTest, PerfExtensionEmpty) {
  SetUpWithFileURL();
  SetUpWithExtensionsProfile("empty");
  RunStartupTest("warm", "extension_empty",
                 false /* cold */, false /* not important */,
                 UITest::DEFAULT_THEME);
}

TEST_F(StartupTest, PerfExtensionToolstrips1) {
  SetUpWithFileURL();
  SetUpWithExtensionsProfile("toolstrips1");
  RunStartupTest("warm", "extension_toolstrip1",
                 false /* cold */, false /* not important */,
                 UITest::DEFAULT_THEME);
}

TEST_F(StartupTest, PerfExtensionToolstrips50) {
  SetUpWithFileURL();
  SetUpWithExtensionsProfile("toolstrips50");
  RunStartupTest("warm", "extension_toolstrip50",
                 false /* cold */, false /* not important */,
                 UITest::DEFAULT_THEME);
}

TEST_F(StartupTest, PerfExtensionContentScript1) {
  SetUpWithFileURL();
  SetUpWithExtensionsProfile("content_scripts1");
  RunStartupTest("warm", "extension_content_scripts1",
                 false /* cold */, false /* not important */,
                 UITest::DEFAULT_THEME);
}

TEST_F(StartupTest, PerfExtensionContentScript50) {
  SetUpWithFileURL();
  SetUpWithExtensionsProfile("content_scripts50");
  RunStartupTest("warm", "extension_content_scripts50",
                 false /* cold */, false /* not important */,
                 UITest::DEFAULT_THEME);
}

#if defined(OS_WIN)
// TODO(port): Enable gears tests on linux/mac once gears is working.
TEST_F(StartupTest, PerfGears) {
  SetUpWithFileURL();
  RunStartupTest("warm", "gears", false /* not cold */,
                 false /* not important */, UITest::DEFAULT_THEME);
}

TEST_F(StartupTest, PerfColdGears) {
  SetUpWithFileURL();
  RunStartupTest("cold", "gears", true /* cold */,
                 false /* not important */, UITest::DEFAULT_THEME);
}
#endif

TEST_F(StartupTest, PerfColdComplexTheme) {
  RunStartupTest("warm", "t-theme", false /* warm */,
                 false /* not important */, UITest::COMPLEX_THEME);
}

#if defined(OS_LINUX)
TEST_F(StartupTest, PerfColdGtkTheme) {
  RunStartupTest("warm", "gtk-theme", false /* warm */,
                 false /* not important */, UITest::NATIVE_THEME);
}

TEST_F(StartupTest, PrefColdNativeFrame) {
  RunStartupTest("warm", "custom-frame", false /* warm */,
                 false /* not important */, UITest::CUSTOM_FRAME);
}

TEST_F(StartupTest, PerfColdNativeFrameGtkTheme) {
  RunStartupTest("warm", "custom-frame-gtk-theme", false /* warm */,
                 false /* not important */, UITest::CUSTOM_FRAME_NATIVE_THEME);
}
#endif

}  // namespace
<commit_msg>Reuse UseReferenceBuild() cleanup in startup test.<commit_after>// Copyright (c) 2006-2008 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 "base/file_util.h"
#include "base/path_service.h"
#include "base/platform_thread.h"
#include "base/string_util.h"
#include "base/test/test_file_util.h"
#include "base/time.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"

using base::TimeDelta;
using base::TimeTicks;

namespace {

class StartupTest : public UITest {
 public:
  StartupTest() {
    show_window_ = true;
    pages_ = "about:blank";
  }
  void SetUp() {}
  void TearDown() {}

  // Load a file on startup rather than about:blank.  This tests a longer
  // startup path, including resource loading and the loading of gears.dll.
  void SetUpWithFileURL() {
    FilePath file_url;
    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &file_url));
    file_url = file_url.AppendASCII("simple.html");
    ASSERT_TRUE(file_util::PathExists(file_url));
    launch_arguments_.AppendLooseValue(file_url.ToWStringHack());

    pages_ = WideToUTF8(file_url.ToWStringHack());
  }

  // Use the given profile in the test data extensions/profiles dir.  This tests
  // startup with extensions installed.
  void SetUpWithExtensionsProfile(const char* profile) {
    FilePath data_dir;
    PathService::Get(chrome::DIR_TEST_DATA, &data_dir);
    data_dir = data_dir.AppendASCII("extensions").AppendASCII("profiles").
        AppendASCII(profile);
    set_template_user_data(data_dir);

    // For now, these tests still depend on toolstrips.
    launch_arguments_.AppendSwitch(switches::kEnableExtensionToolstrips);
  }

  void RunStartupTest(const char* graph, const char* trace,
      bool test_cold, bool important, UITest::ProfileType profile_type) {
    profile_type_ = profile_type;

    // Sets the profile data for the run.  For now, this is only used for
    // the non-default themes test.
    if (profile_type != UITest::DEFAULT_THEME) {
      set_template_user_data(UITest::ComputeTypicalUserDataSource(
          profile_type));
    }

    const int kNumCyclesMax = 20;
    int numCycles = kNumCyclesMax;
// It's ok for unit test code to use getenv(), isn't it?
#if defined(OS_WIN)
#pragma warning( disable : 4996 )
#endif
    const char* numCyclesEnv = getenv("STARTUP_TESTS_NUMCYCLES");
    if (numCyclesEnv && StringToInt(numCyclesEnv, &numCycles))
      LOG(INFO) << "STARTUP_TESTS_NUMCYCLES set in environment, "
                << "so setting numCycles to " << numCycles;

    TimeDelta timings[kNumCyclesMax];
    for (int i = 0; i < numCycles; ++i) {
      if (test_cold) {
        FilePath dir_app;
        ASSERT_TRUE(PathService::Get(chrome::DIR_APP, &dir_app));

        FilePath chrome_exe(dir_app.Append(
            FilePath::FromWStringHack(chrome::kBrowserProcessExecutablePath)));
        ASSERT_TRUE(EvictFileFromSystemCacheWrapper(chrome_exe));
#if defined(OS_WIN)
        // chrome.dll is windows specific.
        FilePath chrome_dll(dir_app.Append(FILE_PATH_LITERAL("chrome.dll")));
        ASSERT_TRUE(EvictFileFromSystemCacheWrapper(chrome_dll));
#endif

#if defined(OS_WIN)
        // TODO(port): Re-enable once gears is working on mac/linux.
        FilePath gears_dll;
        ASSERT_TRUE(PathService::Get(chrome::FILE_GEARS_PLUGIN, &gears_dll));
        ASSERT_TRUE(EvictFileFromSystemCacheWrapper(gears_dll));
#else
        NOTIMPLEMENTED() << "gears not enabled yet";
#endif
      }
      UITest::SetUp();
      TimeTicks end_time = TimeTicks::Now();
      timings[i] = end_time - browser_launch_time_;
      // TODO(beng): Can't shut down so quickly. Figure out why, and fix. If we
      // do, we crash.
      PlatformThread::Sleep(50);
      UITest::TearDown();

      if (i == 0) {
        // Re-use the profile data after first run so that the noise from
        // creating databases doesn't impact all the runs.
        clear_profile_ = false;
        // Clear template_user_data_ so we don't try to copy it over each time
        // through.
        set_template_user_data(FilePath());
      }
    }

    std::string times;
    for (int i = 0; i < numCycles; ++i)
      StringAppendF(&times, "%.2f,", timings[i].InMillisecondsF());
    PrintResultList(graph, "", trace, times, "ms", important);
  }

 protected:
  std::string pages_;
};

TEST_F(StartupTest, PerfWarm) {
  RunStartupTest("warm", "t", false /* not cold */, true /* important */,
                 UITest::DEFAULT_THEME);
}

TEST_F(StartupTest, PerfReferenceWarm) {
  UseReferenceBuild();
  RunStartupTest("warm", "t_ref", false /* not cold */,
                 true /* important */, UITest::DEFAULT_THEME);
}

// TODO(mpcomplete): Should we have reference timings for all these?

TEST_F(StartupTest, PerfCold) {
  RunStartupTest("cold", "t", true /* cold */, false /* not important */,
                 UITest::DEFAULT_THEME);
}

TEST_F(StartupTest, PerfExtensionEmpty) {
  SetUpWithFileURL();
  SetUpWithExtensionsProfile("empty");
  RunStartupTest("warm", "extension_empty",
                 false /* cold */, false /* not important */,
                 UITest::DEFAULT_THEME);
}

TEST_F(StartupTest, PerfExtensionToolstrips1) {
  SetUpWithFileURL();
  SetUpWithExtensionsProfile("toolstrips1");
  RunStartupTest("warm", "extension_toolstrip1",
                 false /* cold */, false /* not important */,
                 UITest::DEFAULT_THEME);
}

TEST_F(StartupTest, PerfExtensionToolstrips50) {
  SetUpWithFileURL();
  SetUpWithExtensionsProfile("toolstrips50");
  RunStartupTest("warm", "extension_toolstrip50",
                 false /* cold */, false /* not important */,
                 UITest::DEFAULT_THEME);
}

TEST_F(StartupTest, PerfExtensionContentScript1) {
  SetUpWithFileURL();
  SetUpWithExtensionsProfile("content_scripts1");
  RunStartupTest("warm", "extension_content_scripts1",
                 false /* cold */, false /* not important */,
                 UITest::DEFAULT_THEME);
}

TEST_F(StartupTest, PerfExtensionContentScript50) {
  SetUpWithFileURL();
  SetUpWithExtensionsProfile("content_scripts50");
  RunStartupTest("warm", "extension_content_scripts50",
                 false /* cold */, false /* not important */,
                 UITest::DEFAULT_THEME);
}

#if defined(OS_WIN)
// TODO(port): Enable gears tests on linux/mac once gears is working.
TEST_F(StartupTest, PerfGears) {
  SetUpWithFileURL();
  RunStartupTest("warm", "gears", false /* not cold */,
                 false /* not important */, UITest::DEFAULT_THEME);
}

TEST_F(StartupTest, PerfColdGears) {
  SetUpWithFileURL();
  RunStartupTest("cold", "gears", true /* cold */,
                 false /* not important */, UITest::DEFAULT_THEME);
}
#endif

TEST_F(StartupTest, PerfColdComplexTheme) {
  RunStartupTest("warm", "t-theme", false /* warm */,
                 false /* not important */, UITest::COMPLEX_THEME);
}

#if defined(OS_LINUX)
TEST_F(StartupTest, PerfColdGtkTheme) {
  RunStartupTest("warm", "gtk-theme", false /* warm */,
                 false /* not important */, UITest::NATIVE_THEME);
}

TEST_F(StartupTest, PrefColdNativeFrame) {
  RunStartupTest("warm", "custom-frame", false /* warm */,
                 false /* not important */, UITest::CUSTOM_FRAME);
}

TEST_F(StartupTest, PerfColdNativeFrameGtkTheme) {
  RunStartupTest("warm", "custom-frame-gtk-theme", false /* warm */,
                 false /* not important */, UITest::CUSTOM_FRAME_NATIVE_THEME);
}
#endif

}  // namespace
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 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 "base/file_util.h"
#include "base/path_service.h"
#include "base/platform_thread.h"
#include "base/string_util.h"
#include "base/test_file_util.h"
#include "base/time.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"

using base::TimeDelta;
using base::TimeTicks;

namespace {

class StartupTest : public UITest {
 public:
  StartupTest() {
    show_window_ = true;
    pages_ = "about:blank";
  }
  void SetUp() {}
  void TearDown() {}

  void RunStartupTest(const char* graph, const char* trace,
      bool test_cold, bool important) {
    const int kNumCyclesMax = 20;
    int numCycles = kNumCyclesMax;
// It's ok for unit test code to use getenv(), isn't it?
#if defined(OS_WIN)
#pragma warning( disable : 4996 )
#endif
    const char* numCyclesEnv = getenv("STARTUP_TESTS_NUMCYCLES");
    if (numCyclesEnv && StringToInt(numCyclesEnv, &numCycles))
      LOG(INFO) << "STARTUP_TESTS_NUMCYCLES set in environment, "
                << "so setting numCycles to " << numCycles;

    TimeDelta timings[kNumCyclesMax];
    for (int i = 0; i < numCycles; ++i) {
      if (test_cold) {
        FilePath dir_app;
        ASSERT_TRUE(PathService::Get(chrome::DIR_APP, &dir_app));

        FilePath chrome_exe(dir_app.Append(
            FilePath::FromWStringHack(chrome::kBrowserProcessExecutablePath)));
        ASSERT_TRUE(EvictFileFromSystemCacheWrapper(chrome_exe));
#if defined(OS_WIN)
        // chrome.dll is windows specific.
        FilePath chrome_dll(dir_app.Append(FILE_PATH_LITERAL("chrome.dll")));
        ASSERT_TRUE(EvictFileFromSystemCacheWrapper(chrome_dll));
#endif

#if defined(OS_WIN)
        // TODO(port): Re-enable once gears is working on mac/linux.
        FilePath gears_dll;
        ASSERT_TRUE(PathService::Get(chrome::FILE_GEARS_PLUGIN, &gears_dll));
        ASSERT_TRUE(EvictFileFromSystemCacheWrapper(gears_dll));
#else
        NOTIMPLEMENTED() << "gears not enabled yet";
#endif
      }

      UITest::SetUp();
      TimeTicks end_time = TimeTicks::Now();
      timings[i] = end_time - browser_launch_time_;
      // TODO(beng): Can't shut down so quickly. Figure out why, and fix. If we
      // do, we crash.
      PlatformThread::Sleep(50);
      UITest::TearDown();

      if (i == 0) {
        // Re-use the profile data after first run so that the noise from
        // creating databases doesn't impact all the runs.
        clear_profile_ = false;
      }
    }

    std::string times;
    for (int i = 0; i < numCycles; ++i)
      StringAppendF(&times, "%.2f,", timings[i].InMillisecondsF());
    PrintResultList(graph, "", trace, times, "ms", important);
  }

 protected:
  std::string pages_;
};

class StartupReferenceTest : public StartupTest {
 public:
  // override the browser directory that is used by UITest::SetUp to cause it
  // to use the reference build instead.
  void SetUp() {
    FilePath dir;
    PathService::Get(chrome::DIR_TEST_TOOLS, &dir);
    dir = dir.AppendASCII("reference_build");
#if defined(OS_WIN)
    dir = dir.AppendASCII("chrome");
#elif defined(OS_LINUX)
    dir = dir.AppendASCII("chrome_linux");
#elif defined(OS_MACOSX)
    dir = dir.AppendASCII("chrome_mac");
#endif
    browser_directory_ = dir;
  }
};

class StartupFileTest : public StartupTest {
 public:
  // Load a file on startup rather than about:blank.  This tests a longer
  // startup path, including resource loading and the loading of gears.dll.
  void SetUp() {
    FilePath file_url;
    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &file_url));
    file_url = file_url.AppendASCII("empty.html");
    ASSERT_TRUE(file_util::PathExists(file_url));
    launch_arguments_.AppendLooseValue(file_url.ToWStringHack());

    pages_ = WideToUTF8(file_url.ToWStringHack());
  }
};

TEST_F(StartupTest, Perf) {
  RunStartupTest("warm", "t", false /* not cold */, true /* important */);
}

#if defined(OS_WIN) || defined(OS_LINUX)
// TODO(port): We need a mac reference build checked in for this.
TEST_F(StartupReferenceTest, Perf) {
  RunStartupTest("warm", "t_ref", false /* not cold */,
                 true /* important */);
}
#endif

// TODO(mpcomplete): Should we have reference timings for all these?

TEST_F(StartupTest, PerfCold) {
  RunStartupTest("cold", "t", true /* cold */, false /* not important */);
}

#if defined(OS_WIN)
// TODO(port): Enable gears tests on linux/mac once gears is working.
TEST_F(StartupFileTest, PerfGears) {
  RunStartupTest("warm", "gears", false /* not cold */,
                 false /* not important */);
}

TEST_F(StartupFileTest, PerfColdGears) {
  RunStartupTest("cold", "gears", true /* cold */,
                 false /* not important */);
}
#endif

}  // namespace
<commit_msg>Enable the perf reference test. Review URL: http://codereview.chromium.org/122043<commit_after>// Copyright (c) 2006-2008 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 "base/file_util.h"
#include "base/path_service.h"
#include "base/platform_thread.h"
#include "base/string_util.h"
#include "base/test_file_util.h"
#include "base/time.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"

using base::TimeDelta;
using base::TimeTicks;

namespace {

class StartupTest : public UITest {
 public:
  StartupTest() {
    show_window_ = true;
    pages_ = "about:blank";
  }
  void SetUp() {}
  void TearDown() {}

  void RunStartupTest(const char* graph, const char* trace,
      bool test_cold, bool important) {
    const int kNumCyclesMax = 20;
    int numCycles = kNumCyclesMax;
// It's ok for unit test code to use getenv(), isn't it?
#if defined(OS_WIN)
#pragma warning( disable : 4996 )
#endif
    const char* numCyclesEnv = getenv("STARTUP_TESTS_NUMCYCLES");
    if (numCyclesEnv && StringToInt(numCyclesEnv, &numCycles))
      LOG(INFO) << "STARTUP_TESTS_NUMCYCLES set in environment, "
                << "so setting numCycles to " << numCycles;

    TimeDelta timings[kNumCyclesMax];
    for (int i = 0; i < numCycles; ++i) {
      if (test_cold) {
        FilePath dir_app;
        ASSERT_TRUE(PathService::Get(chrome::DIR_APP, &dir_app));

        FilePath chrome_exe(dir_app.Append(
            FilePath::FromWStringHack(chrome::kBrowserProcessExecutablePath)));
        ASSERT_TRUE(EvictFileFromSystemCacheWrapper(chrome_exe));
#if defined(OS_WIN)
        // chrome.dll is windows specific.
        FilePath chrome_dll(dir_app.Append(FILE_PATH_LITERAL("chrome.dll")));
        ASSERT_TRUE(EvictFileFromSystemCacheWrapper(chrome_dll));
#endif

#if defined(OS_WIN)
        // TODO(port): Re-enable once gears is working on mac/linux.
        FilePath gears_dll;
        ASSERT_TRUE(PathService::Get(chrome::FILE_GEARS_PLUGIN, &gears_dll));
        ASSERT_TRUE(EvictFileFromSystemCacheWrapper(gears_dll));
#else
        NOTIMPLEMENTED() << "gears not enabled yet";
#endif
      }

      UITest::SetUp();
      TimeTicks end_time = TimeTicks::Now();
      timings[i] = end_time - browser_launch_time_;
      // TODO(beng): Can't shut down so quickly. Figure out why, and fix. If we
      // do, we crash.
      PlatformThread::Sleep(50);
      UITest::TearDown();

      if (i == 0) {
        // Re-use the profile data after first run so that the noise from
        // creating databases doesn't impact all the runs.
        clear_profile_ = false;
      }
    }

    std::string times;
    for (int i = 0; i < numCycles; ++i)
      StringAppendF(&times, "%.2f,", timings[i].InMillisecondsF());
    PrintResultList(graph, "", trace, times, "ms", important);
  }

 protected:
  std::string pages_;
};

class StartupReferenceTest : public StartupTest {
 public:
  // override the browser directory that is used by UITest::SetUp to cause it
  // to use the reference build instead.
  void SetUp() {
    FilePath dir;
    PathService::Get(chrome::DIR_TEST_TOOLS, &dir);
    dir = dir.AppendASCII("reference_build");
#if defined(OS_WIN)
    dir = dir.AppendASCII("chrome");
#elif defined(OS_LINUX)
    dir = dir.AppendASCII("chrome_linux");
#elif defined(OS_MACOSX)
    dir = dir.AppendASCII("chrome_mac");
#endif
    browser_directory_ = dir;
  }
};

class StartupFileTest : public StartupTest {
 public:
  // Load a file on startup rather than about:blank.  This tests a longer
  // startup path, including resource loading and the loading of gears.dll.
  void SetUp() {
    FilePath file_url;
    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &file_url));
    file_url = file_url.AppendASCII("empty.html");
    ASSERT_TRUE(file_util::PathExists(file_url));
    launch_arguments_.AppendLooseValue(file_url.ToWStringHack());

    pages_ = WideToUTF8(file_url.ToWStringHack());
  }
};

TEST_F(StartupTest, Perf) {
  RunStartupTest("warm", "t", false /* not cold */, true /* important */);
}

// TODO(port): We need a mac reference build checked in for this.
TEST_F(StartupReferenceTest, Perf) {
  RunStartupTest("warm", "t_ref", false /* not cold */,
                 true /* important */);
}

// TODO(mpcomplete): Should we have reference timings for all these?

TEST_F(StartupTest, PerfCold) {
  RunStartupTest("cold", "t", true /* cold */, false /* not important */);
}

#if defined(OS_WIN)
// TODO(port): Enable gears tests on linux/mac once gears is working.
TEST_F(StartupFileTest, PerfGears) {
  RunStartupTest("warm", "gears", false /* not cold */,
                 false /* not important */);
}

TEST_F(StartupFileTest, PerfColdGears) {
  RunStartupTest("cold", "gears", true /* cold */,
                 false /* not important */);
}
#endif

}  // namespace
<|endoftext|>


<commit_before>#include <libudev.h>
#include <pthread.h>

#include "detection.h"
#include "deviceList.h"

using namespace std;

/**********************************
 * Local defines
 **********************************/
#define DEVICE_ACTION_ADDED             "add"
#define DEVICE_ACTION_REMOVED           "remove"

#define DEVICE_TYPE_DEVICE              "usb_device"

#define DEVICE_PROPERTY_NAME            "ID_MODEL"
#define DEVICE_PROPERTY_SERIAL          "ID_SERIAL_SHORT"
#define DEVICE_PROPERTY_VENDOR          "ID_VENDOR"

/**********************************
 * Local typedefs
 **********************************/

/**********************************
 * Local Variables
 **********************************/
ListResultItem_t* currentItem;
bool isAdded;

struct udev *udev;
struct udev_enumerate *enumerate;
struct udev_list_entry *devices, *dev_list_entry;
struct udev_device *dev;

struct udev_monitor *mon;
int fd;

pthread_t thread;
pthread_mutex_t notify_mutex;
pthread_cond_t notify_cv;
/**********************************
 * Local Helper Functions protoypes
 **********************************/
void BuildInitialDeviceList();

void* ThreadFunc(void* ptr);

bool isRunning = false;

/**********************************
 * Public Functions
 **********************************/
void NotifyAsync(uv_work_t* req)
{
    pthread_mutex_lock(&notify_mutex);

    pthread_cond_wait(&notify_cv, &notify_mutex);

    pthread_mutex_unlock(&notify_mutex);
}

void NotifyFinished(uv_work_t* req)
{
    pthread_mutex_lock(&notify_mutex);

    if (isRunning)
    {
        if (isAdded)
        {
            NotifyAdded(currentItem);
        } else
        {
            NotifyRemoved(currentItem);
        }
    }

    pthread_mutex_unlock(&notify_mutex);

    if (isRunning)
    {
        uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished);
    }
}

void Start()
{
    isRunning = true;
    uv_work_t* req = new uv_work_t();
    uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished);

    pthread_create(&thread, NULL, ThreadFunc, NULL);
}

void Stop()
{
    isRunning = false;
    pthread_mutex_lock(&notify_mutex);
    pthread_cond_signal(&notify_cv);
    pthread_mutex_unlock(&notify_mutex);

    // pthread_exit(&thread);
}

void InitDetection()
{
    /* Create the udev object */
    udev = udev_new();
    if (!udev)
    {
        printf("Can't create udev\n");
        return;
    }

    /* Set up a monitor to monitor devices */
    mon = udev_monitor_new_from_netlink(udev, "udev");
    udev_monitor_enable_receiving(mon);

    /* Get the file descriptor (fd) for the monitor.
       This fd will get passed to select() */
    fd = udev_monitor_get_fd(mon);

    BuildInitialDeviceList();

    pthread_mutex_init(&notify_mutex, NULL);
    pthread_cond_init(&notify_cv, NULL);

    Start();
}

void EIO_Find(uv_work_t* req)
{
    ListBaton* data = static_cast<ListBaton*>(req->data);

    CreateFilteredList(&data->results, data->vid, data->pid);
}

/**********************************
 * Local Functions
 **********************************/
 ListResultItem_t* GetProperties(struct udev_device* dev, ListResultItem_t* item)
 {
    struct udev_list_entry* sysattrs;
    struct udev_list_entry* entry;
    sysattrs = udev_device_get_properties_list_entry(dev);
    udev_list_entry_foreach(entry, sysattrs)
    {
        const char *name, *value;
        name = udev_list_entry_get_name(entry);
        value = udev_list_entry_get_value(entry);

        if(strcmp(name, DEVICE_PROPERTY_NAME) == 0)
        {
            item->deviceName = value;
        }
        else if(strcmp(name, DEVICE_PROPERTY_SERIAL) == 0)
        {
            item->serialNumber = value;
        }
        else if(strcmp(name, DEVICE_PROPERTY_VENDOR) == 0)
        {
            item->manufacturer = value;
        }
    }
    item->vendorId = strtol (udev_device_get_sysattr_value(dev,"idVendor"), NULL, 16);
    item->productId = strtol (udev_device_get_sysattr_value(dev,"idProduct"), NULL, 16);
    item->deviceAddress = 0;
    item->locationId = 0;

    return item;
}

void DeviceAdded(struct udev_device* dev)
{
    DeviceItem_t* item = new DeviceItem_t();
    GetProperties(dev, &item->deviceParams);

    AddItemToList((char *)udev_device_get_devnode(dev), item);

    currentItem = &item->deviceParams;
    isAdded = true;

    pthread_mutex_lock(&notify_mutex);
    pthread_cond_signal(&notify_cv);
    pthread_mutex_unlock(&notify_mutex);
}

void DeviceRemoved(struct udev_device* dev)
{
    ListResultItem_t* item = NULL;

    if(IsItemAlreadyStored((char *)udev_device_get_devnode(dev)))
    {
        DeviceItem_t* deviceItem = GetItemFromList( (char *)udev_device_get_devnode(dev));
        if(deviceItem)
        {
            item = CopyElement(&deviceItem->deviceParams);
        }
        RemoveItemFromList(deviceItem);
        delete deviceItem;
    }

    if(item == NULL)
    {
        item = new ListResultItem_t();
        GetProperties(dev, item);
    }

    currentItem = item;
    isAdded = false;

    pthread_mutex_lock(&notify_mutex);
    pthread_cond_signal(&notify_cv);
    pthread_mutex_unlock(&notify_mutex);
}

void* ThreadFunc(void* ptr)
{
    while (1)
    {
        /* Make the call to receive the device.
           select() ensured that this will not block. */
        dev = udev_monitor_receive_device(mon);
        if (dev)
        {
            if(udev_device_get_devtype(dev) && strcmp(udev_device_get_devtype(dev), DEVICE_TYPE_DEVICE) == 0)
            {
                if(strcmp(udev_device_get_action(dev), DEVICE_ACTION_ADDED) == 0)
                {
                    DeviceAdded(dev);
                }
                else if(strcmp(udev_device_get_action(dev), DEVICE_ACTION_REMOVED) == 0)
                {
                    DeviceRemoved(dev);
                }
            }
            udev_device_unref(dev);
        }
    }

    return NULL;
}

void BuildInitialDeviceList()
{
    /* Create a list of the devices */
    enumerate = udev_enumerate_new(udev);
    udev_enumerate_scan_devices(enumerate);
    devices = udev_enumerate_get_list_entry(enumerate);
    /* For each item enumerated, print out its information.
       udev_list_entry_foreach is a macro which expands to
       a loop. The loop will be executed for each member in
       devices, setting dev_list_entry to a list entry
       which contains the device's path in /sys. */
    udev_list_entry_foreach(dev_list_entry, devices)
    {
        const char *path;

        /* Get the filename of the /sys entry for the device
           and create a udev_device object (dev) representing it */
        path = udev_list_entry_get_name(dev_list_entry);
        dev = udev_device_new_from_syspath(udev, path);

        /* usb_device_get_devnode() returns the path to the device node
           itself in /dev. */
        if(udev_device_get_devnode(dev) == NULL || udev_device_get_sysattr_value(dev,"idVendor") == NULL)
        {
            continue;
        }

        /* From here, we can call get_sysattr_value() for each file
           in the device's /sys entry. The strings passed into these
           functions (idProduct, idVendor, serial, etc.) correspond
           directly to the files in the /sys directory which
           represents the USB device. Note that USB strings are
           Unicode, UCS2 encoded, but the strings returned from
           udev_device_get_sysattr_value() are UTF-8 encoded. */

        DeviceItem_t* item = new DeviceItem_t();
        item->deviceParams.vendorId = strtol (udev_device_get_sysattr_value(dev,"idVendor"), NULL, 16);
        item->deviceParams.productId = strtol (udev_device_get_sysattr_value(dev,"idProduct"), NULL, 16);
        if(udev_device_get_sysattr_value(dev,"product") != NULL)
        {
            item->deviceParams.deviceName = udev_device_get_sysattr_value(dev,"product");
        }
        if(udev_device_get_sysattr_value(dev,"manufacturer") != NULL)
        {
            item->deviceParams.manufacturer = udev_device_get_sysattr_value(dev,"manufacturer");
        }
        if(udev_device_get_sysattr_value(dev,"serial") != NULL)
        {
            item->deviceParams.serialNumber = udev_device_get_sysattr_value(dev, "serial");
        }
        item->deviceParams.deviceAddress = 0;
        item->deviceParams.locationId = 0;

        item->deviceState = DeviceState_Connect;

        AddItemToList((char *)udev_device_get_devnode(dev), item);

        udev_device_unref(dev);
    }
    /* Free the enumerator object */
    udev_enumerate_unref(enumerate);
}<commit_msg>Event handling for linux changed<commit_after>#include <libudev.h>
#include <pthread.h>

#include "detection.h"
#include "deviceList.h"

using namespace std;

/**********************************
 * Local defines
 **********************************/
#define DEVICE_ACTION_ADDED             "add"
#define DEVICE_ACTION_REMOVED           "remove"

#define DEVICE_TYPE_DEVICE              "usb_device"

#define DEVICE_PROPERTY_NAME            "ID_MODEL"
#define DEVICE_PROPERTY_SERIAL          "ID_SERIAL_SHORT"
#define DEVICE_PROPERTY_VENDOR          "ID_VENDOR"

/**********************************
 * Local typedefs
 **********************************/

/**********************************
 * Local Variables
 **********************************/
ListResultItem_t* currentItem;
bool isAdded;

struct udev *udev;
struct udev_enumerate *enumerate;
struct udev_list_entry *devices, *dev_list_entry;
struct udev_device *dev;

struct udev_monitor *mon;
int fd;

pthread_t thread;
pthread_mutex_t notify_mutex;
pthread_cond_t notifyNewDevice;
pthread_cond_t notifyDeviceHandled;

bool newDeviceAvailable = false;
bool deviceHandled = true;

bool isRunning = false;
/**********************************
 * Local Helper Functions protoypes
 **********************************/
void BuildInitialDeviceList();

void* ThreadFunc(void* ptr);
void WaitForDeviceHandled();
void SignalDeviceHandled();
void WaitForNewDevice();
void SignalDeviceAvailable();

/**********************************
 * Public Functions
 **********************************/
void NotifyAsync(uv_work_t* req)
{
    WaitForNewDevice();
}

void NotifyFinished(uv_work_t* req)
{
    if (isRunning)
    {
        if (isAdded)
        {
            NotifyAdded(currentItem);
        }
        else
        {
            NotifyRemoved(currentItem);
        }
    }

    if (isRunning)
    {
        SignalDeviceHandled();
        uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished);
    }
}

void Start()
{
    isRunning = true;
    uv_work_t* req = new uv_work_t();
    uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished);

    pthread_create(&thread, NULL, ThreadFunc, NULL);
}

void Stop()
{
    isRunning = false;
    pthread_mutex_lock(&notify_mutex);
    pthread_cond_signal(&notifyNewDevice);
    pthread_mutex_unlock(&notify_mutex);

    // pthread_exit(&thread);
}

void InitDetection()
{
    /* Create the udev object */
    udev = udev_new();
    if (!udev)
    {
        printf("Can't create udev\n");
        return;
    }

    /* Set up a monitor to monitor devices */
    mon = udev_monitor_new_from_netlink(udev, "udev");
    udev_monitor_enable_receiving(mon);

    /* Get the file descriptor (fd) for the monitor.
       This fd will get passed to select() */
    fd = udev_monitor_get_fd(mon);

    BuildInitialDeviceList();

    pthread_mutex_init(&notify_mutex, NULL);
    pthread_cond_init(&notifyNewDevice, NULL);
    pthread_cond_init(&notifyDeviceHandled, NULL);

    Start();
}

void EIO_Find(uv_work_t* req)
{
    ListBaton* data = static_cast<ListBaton*>(req->data);

    CreateFilteredList(&data->results, data->vid, data->pid);
}

/**********************************
 * Local Functions
 **********************************/
void WaitForDeviceHandled()
{
    pthread_mutex_lock(&notify_mutex);
    if(deviceHandled == false)
    {
        pthread_cond_wait(&notifyDeviceHandled, &notify_mutex);
    }
    deviceHandled = false;
    pthread_mutex_unlock(&notify_mutex);
}

void SignalDeviceHandled()
{
    pthread_mutex_lock(&notify_mutex);
    deviceHandled = true;
    pthread_cond_signal(&notifyDeviceHandled);
    pthread_mutex_unlock(&notify_mutex);
}

void WaitForNewDevice()
{
    pthread_mutex_lock(&notify_mutex);
    if(newDeviceAvailable == false)
    {
        pthread_cond_wait(&notifyNewDevice, &notify_mutex);
    }
    newDeviceAvailable = false;
    pthread_mutex_unlock(&notify_mutex);
}

void SignalDeviceAvailable()
{
    pthread_mutex_lock(&notify_mutex);
    newDeviceAvailable = true;
    pthread_cond_signal(&notifyNewDevice);
    pthread_mutex_unlock(&notify_mutex);
}

 ListResultItem_t* GetProperties(struct udev_device* dev, ListResultItem_t* item)
 {
    struct udev_list_entry* sysattrs;
    struct udev_list_entry* entry;
    sysattrs = udev_device_get_properties_list_entry(dev);
    udev_list_entry_foreach(entry, sysattrs)
    {
        const char *name, *value;
        name = udev_list_entry_get_name(entry);
        value = udev_list_entry_get_value(entry);

        if(strcmp(name, DEVICE_PROPERTY_NAME) == 0)
        {
            item->deviceName = value;
        }
        else if(strcmp(name, DEVICE_PROPERTY_SERIAL) == 0)
        {
            item->serialNumber = value;
        }
        else if(strcmp(name, DEVICE_PROPERTY_VENDOR) == 0)
        {
            item->manufacturer = value;
        }
    }
    item->vendorId = strtol (udev_device_get_sysattr_value(dev,"idVendor"), NULL, 16);
    item->productId = strtol (udev_device_get_sysattr_value(dev,"idProduct"), NULL, 16);
    item->deviceAddress = 0;
    item->locationId = 0;

    return item;
}

void DeviceAdded(struct udev_device* dev)
{
    DeviceItem_t* item = new DeviceItem_t();
    GetProperties(dev, &item->deviceParams);

    AddItemToList((char *)udev_device_get_devnode(dev), item);

    currentItem = &item->deviceParams;
    isAdded = true;

    SignalDeviceAvailable();
}

void DeviceRemoved(struct udev_device* dev)
{
    ListResultItem_t* item = NULL;

    if(IsItemAlreadyStored((char *)udev_device_get_devnode(dev)))
    {
        DeviceItem_t* deviceItem = GetItemFromList( (char *)udev_device_get_devnode(dev));
        if(deviceItem)
        {
            item = CopyElement(&deviceItem->deviceParams);
        }
        RemoveItemFromList(deviceItem);
        delete deviceItem;
    }

    if(item == NULL)
    {
        item = new ListResultItem_t();
        GetProperties(dev, item);
    }

    currentItem = item;
    isAdded = false;

    SignalDeviceAvailable();
}

void* ThreadFunc(void* ptr)
{
    while (1)
    {
        /* Make the call to receive the device.
           select() ensured that this will not block. */
        dev = udev_monitor_receive_device(mon);
        if (dev)
        {
            if(udev_device_get_devtype(dev) && strcmp(udev_device_get_devtype(dev), DEVICE_TYPE_DEVICE) == 0)
            {
                if(strcmp(udev_device_get_action(dev), DEVICE_ACTION_ADDED) == 0)
                {
                    WaitForDeviceHandled();
                    DeviceAdded(dev);
                }
                else if(strcmp(udev_device_get_action(dev), DEVICE_ACTION_REMOVED) == 0)
                {
                    WaitForDeviceHandled();
                    DeviceRemoved(dev);
                }
            }
            udev_device_unref(dev);
        }
    }

    return NULL;
}

void BuildInitialDeviceList()
{
    /* Create a list of the devices */
    enumerate = udev_enumerate_new(udev);
    udev_enumerate_scan_devices(enumerate);
    devices = udev_enumerate_get_list_entry(enumerate);
    /* For each item enumerated, print out its information.
       udev_list_entry_foreach is a macro which expands to
       a loop. The loop will be executed for each member in
       devices, setting dev_list_entry to a list entry
       which contains the device's path in /sys. */
    udev_list_entry_foreach(dev_list_entry, devices)
    {
        const char *path;

        /* Get the filename of the /sys entry for the device
           and create a udev_device object (dev) representing it */
        path = udev_list_entry_get_name(dev_list_entry);
        dev = udev_device_new_from_syspath(udev, path);

        /* usb_device_get_devnode() returns the path to the device node
           itself in /dev. */
        if(udev_device_get_devnode(dev) == NULL || udev_device_get_sysattr_value(dev,"idVendor") == NULL)
        {
            continue;
        }

        /* From here, we can call get_sysattr_value() for each file
           in the device's /sys entry. The strings passed into these
           functions (idProduct, idVendor, serial, etc.) correspond
           directly to the files in the /sys directory which
           represents the USB device. Note that USB strings are
           Unicode, UCS2 encoded, but the strings returned from
           udev_device_get_sysattr_value() are UTF-8 encoded. */

        DeviceItem_t* item = new DeviceItem_t();
        item->deviceParams.vendorId = strtol (udev_device_get_sysattr_value(dev,"idVendor"), NULL, 16);
        item->deviceParams.productId = strtol (udev_device_get_sysattr_value(dev,"idProduct"), NULL, 16);
        if(udev_device_get_sysattr_value(dev,"product") != NULL)
        {
            item->deviceParams.deviceName = udev_device_get_sysattr_value(dev,"product");
        }
        if(udev_device_get_sysattr_value(dev,"manufacturer") != NULL)
        {
            item->deviceParams.manufacturer = udev_device_get_sysattr_value(dev,"manufacturer");
        }
        if(udev_device_get_sysattr_value(dev,"serial") != NULL)
        {
            item->deviceParams.serialNumber = udev_device_get_sysattr_value(dev, "serial");
        }
        item->deviceParams.deviceAddress = 0;
        item->deviceParams.locationId = 0;

        item->deviceState = DeviceState_Connect;

        AddItemToList((char *)udev_device_get_devnode(dev), item);

        udev_device_unref(dev);
    }
    /* Free the enumerator object */
    udev_enumerate_unref(enumerate);
}<|endoftext|>


<commit_before>#include <utility>

#include "drawtypes/label.hpp"
#include "utils/factory.hpp"

POLYBAR_NS

namespace drawtypes {
  string label::get() const {
    return m_tokenized;
  }

  label::operator bool() {
    return !m_tokenized.empty();
  }

  label_t label::clone() {
    vector<token> tokens;
    if (!m_tokens.empty()) {
      std::back_insert_iterator<decltype(tokens)> back_it(tokens);
      std::copy(m_tokens.begin(), m_tokens.end(), back_it);
    }
    return factory_util::shared<label>(m_text, m_foreground, m_background, m_underline, m_overline, m_font, m_padding,
        m_margin, m_maxlen, m_ellipsis, move(tokens));
  }

  void label::reset_tokens() {
    m_tokenized = m_text;
  }

  bool label::has_token(const string& token) {
    return m_text.find(token) != string::npos;
  }

  void label::replace_token(const string& token, string replacement) {
    if (!has_token(token)) {
      return;
    }

    for (auto&& tok : m_tokens) {
      if (token == tok.token) {
        if (tok.max != 0_z && replacement.length() > tok.max) {
          replacement = replacement.erase(tok.max) + tok.suffix;
        } else if (tok.min != 0_z && replacement.length() < tok.min) {
          replacement.insert(0_z, tok.min - replacement.length(), ' ');
        }
        m_tokenized = string_util::replace_all(m_tokenized, token, move(replacement));
      }
    }
  }

  void label::replace_defined_values(const label_t& label) {
    if (!label->m_foreground.empty()) {
      m_foreground = label->m_foreground;
    }
    if (!label->m_background.empty()) {
      m_background = label->m_background;
    }
    if (!label->m_underline.empty()) {
      m_underline = label->m_underline;
    }
    if (!label->m_overline.empty()) {
      m_overline = label->m_overline;
    }
    if (label->m_font != 0) {
      m_font = label->m_font;
    }
    if (label->m_padding.left != 0U) {
      m_padding.left = label->m_padding.left;
    }
    if (label->m_padding.right != 0U) {
      m_padding.right = label->m_padding.right;
    }
    if (label->m_margin.left != 0U) {
      m_margin.left = label->m_margin.left;
    }
    if (label->m_margin.right != 0U) {
      m_margin.right = label->m_margin.right;
    }
    if (label->m_maxlen != 0_z) {
      m_maxlen = label->m_maxlen;
      m_ellipsis = label->m_ellipsis;
    }
  }

  void label::copy_undefined(const label_t& label) {
    if (m_foreground.empty() && !label->m_foreground.empty()) {
      m_foreground = label->m_foreground;
    }
    if (m_background.empty() && !label->m_background.empty()) {
      m_background = label->m_background;
    }
    if (m_underline.empty() && !label->m_underline.empty()) {
      m_underline = label->m_underline;
    }
    if (m_overline.empty() && !label->m_overline.empty()) {
      m_overline = label->m_overline;
    }
    if (m_font == 0 && label->m_font != 0) {
      m_font = label->m_font;
    }
    if (m_padding.left == 0U && label->m_padding.left != 0U) {
      m_padding.left = label->m_padding.left;
    }
    if (m_padding.right == 0U && label->m_padding.right != 0U) {
      m_padding.right = label->m_padding.right;
    }
    if (m_margin.left == 0U && label->m_margin.left != 0U) {
      m_margin.left = label->m_margin.left;
    }
    if (m_margin.right == 0U && label->m_margin.right != 0U) {
      m_margin.right = label->m_margin.right;
    }
    if (m_maxlen == 0_z && label->m_maxlen != 0_z) {
      m_maxlen = label->m_maxlen;
      m_ellipsis = label->m_ellipsis;
    }
  }

  /**
   * Create a label by loading values from the configuration
   */
  label_t load_label(const config& conf, const string& section, string name, bool required, string def) {
    vector<token> tokens;
    size_t start, end, pos;

    name = string_util::ltrim(string_util::rtrim(move(name), '>'), '<');

    string text;

    struct side_values padding {
    }, margin{};

    if (required) {
      text = conf.get(section, name);
    } else {
      text = conf.get(section, name, move(def));
    }

    size_t len{text.size()};

    if (len > 2 && text[0] == '"' && text[len - 1] == '"') {
      text = text.substr(1, len - 2);
    }

    const auto get_left_right = [&](string key) {
      auto value = conf.get(section, key, 0U);
      auto left = conf.get(section, key + "-left", value);
      auto right = conf.get(section, key + "-right", value);
      return side_values{static_cast<uint16_t>(left), static_cast<uint16_t>(right)};
    };

    padding = get_left_right(name + "-padding");
    margin = get_left_right(name + "-margin");

    string line{text};

    while ((start = line.find('%')) != string::npos && (end = line.find('%', start + 1)) != string::npos) {
      auto token_str = line.substr(start, end - start + 1);

      // ignore false positives (lemonbar-style declarations)
      if (token_str[1] == '{') {
        line.erase(0, start + 1);
        continue;
      }

      line.erase(start, end - start + 1);
      tokens.emplace_back(token{token_str, 0_z, 0_z});
      auto& token = tokens.back();

      // find min delimiter
      if ((pos = token_str.find(':')) == string::npos) {
        continue;
      }

      // strip min/max specifiers from the label string token
      token.token = token_str.substr(0, pos) + '%';
      text = string_util::replace(text, token_str, token.token);

      try {
        token.min = std::stoul(&token_str[pos + 1], nullptr, 10);
      } catch (const std::invalid_argument& err) {
        continue;
      }

      // find max delimiter
      if ((pos = token_str.find(':', pos + 1)) == string::npos) {
        continue;
      }

      try {
        token.max = std::stoul(&token_str[pos + 1], nullptr, 10);
      } catch (const std::invalid_argument& err) {
        continue;
      }

      // ignore max lengths less than min
      if (token.max < token.min) {
        token.max = 0_z;
      }

      // find suffix delimiter
      if ((pos = token_str.find(':', pos + 1)) != string::npos) {
        token.suffix = token_str.substr(pos + 1, end - pos - 1);
      }
    }

    // clang-format off
    return factory_util::shared<label>(text,
        conf.get(section, name + "-foreground", ""s),
        conf.get(section, name + "-background", ""s),
        conf.get(section, name + "-underline", ""s),
        conf.get(section, name + "-overline", ""s),
        conf.get(section, name + "-font", 0),
        padding,
        margin,
        conf.get(section, name + "-maxlen", 0_z),
        conf.get(section, name + "-ellipsis", true),
        move(tokens));
    // clang-format on
  }

  /**
   * Create a label by loading optional values from the configuration
   */
  label_t load_optional_label(const config& conf, string section, string name, string def) {
    return load_label(conf, move(section), move(name), false, move(def));
  }

  /**
   * Create an icon by loading values from the configuration
   */
  icon_t load_icon(const config& conf, string section, string name, bool required, string def) {
    return load_label(conf, move(section), move(name), required, move(def));
  }

  /**
   * Create an icon by loading optional values from the configuration
   */
  icon_t load_optional_icon(const config& conf, string section, string name, string def) {
    return load_icon(conf, move(section), move(name), false, move(def));
  }
}

POLYBAR_NS_END
<commit_msg>fix(label): Drop token close character from suffix substring<commit_after>#include <utility>

#include "drawtypes/label.hpp"
#include "utils/factory.hpp"

POLYBAR_NS

namespace drawtypes {
  string label::get() const {
    return m_tokenized;
  }

  label::operator bool() {
    return !m_tokenized.empty();
  }

  label_t label::clone() {
    vector<token> tokens;
    if (!m_tokens.empty()) {
      std::back_insert_iterator<decltype(tokens)> back_it(tokens);
      std::copy(m_tokens.begin(), m_tokens.end(), back_it);
    }
    return factory_util::shared<label>(m_text, m_foreground, m_background, m_underline, m_overline, m_font, m_padding,
        m_margin, m_maxlen, m_ellipsis, move(tokens));
  }

  void label::reset_tokens() {
    m_tokenized = m_text;
  }

  bool label::has_token(const string& token) {
    return m_text.find(token) != string::npos;
  }

  void label::replace_token(const string& token, string replacement) {
    if (!has_token(token)) {
      return;
    }

    for (auto&& tok : m_tokens) {
      if (token == tok.token) {
        if (tok.max != 0_z && replacement.length() > tok.max) {
          replacement = replacement.erase(tok.max) + tok.suffix;
        } else if (tok.min != 0_z && replacement.length() < tok.min) {
          replacement.insert(0_z, tok.min - replacement.length(), ' ');
        }
        m_tokenized = string_util::replace_all(m_tokenized, token, move(replacement));
      }
    }
  }

  void label::replace_defined_values(const label_t& label) {
    if (!label->m_foreground.empty()) {
      m_foreground = label->m_foreground;
    }
    if (!label->m_background.empty()) {
      m_background = label->m_background;
    }
    if (!label->m_underline.empty()) {
      m_underline = label->m_underline;
    }
    if (!label->m_overline.empty()) {
      m_overline = label->m_overline;
    }
    if (label->m_font != 0) {
      m_font = label->m_font;
    }
    if (label->m_padding.left != 0U) {
      m_padding.left = label->m_padding.left;
    }
    if (label->m_padding.right != 0U) {
      m_padding.right = label->m_padding.right;
    }
    if (label->m_margin.left != 0U) {
      m_margin.left = label->m_margin.left;
    }
    if (label->m_margin.right != 0U) {
      m_margin.right = label->m_margin.right;
    }
    if (label->m_maxlen != 0_z) {
      m_maxlen = label->m_maxlen;
      m_ellipsis = label->m_ellipsis;
    }
  }

  void label::copy_undefined(const label_t& label) {
    if (m_foreground.empty() && !label->m_foreground.empty()) {
      m_foreground = label->m_foreground;
    }
    if (m_background.empty() && !label->m_background.empty()) {
      m_background = label->m_background;
    }
    if (m_underline.empty() && !label->m_underline.empty()) {
      m_underline = label->m_underline;
    }
    if (m_overline.empty() && !label->m_overline.empty()) {
      m_overline = label->m_overline;
    }
    if (m_font == 0 && label->m_font != 0) {
      m_font = label->m_font;
    }
    if (m_padding.left == 0U && label->m_padding.left != 0U) {
      m_padding.left = label->m_padding.left;
    }
    if (m_padding.right == 0U && label->m_padding.right != 0U) {
      m_padding.right = label->m_padding.right;
    }
    if (m_margin.left == 0U && label->m_margin.left != 0U) {
      m_margin.left = label->m_margin.left;
    }
    if (m_margin.right == 0U && label->m_margin.right != 0U) {
      m_margin.right = label->m_margin.right;
    }
    if (m_maxlen == 0_z && label->m_maxlen != 0_z) {
      m_maxlen = label->m_maxlen;
      m_ellipsis = label->m_ellipsis;
    }
  }

  /**
   * Create a label by loading values from the configuration
   */
  label_t load_label(const config& conf, const string& section, string name, bool required, string def) {
    vector<token> tokens;
    size_t start, end, pos;

    name = string_util::ltrim(string_util::rtrim(move(name), '>'), '<');

    string text;

    struct side_values padding {
    }, margin{};

    if (required) {
      text = conf.get(section, name);
    } else {
      text = conf.get(section, name, move(def));
    }

    size_t len{text.size()};

    if (len > 2 && text[0] == '"' && text[len - 1] == '"') {
      text = text.substr(1, len - 2);
    }

    const auto get_left_right = [&](string key) {
      auto value = conf.get(section, key, 0U);
      auto left = conf.get(section, key + "-left", value);
      auto right = conf.get(section, key + "-right", value);
      return side_values{static_cast<uint16_t>(left), static_cast<uint16_t>(right)};
    };

    padding = get_left_right(name + "-padding");
    margin = get_left_right(name + "-margin");

    string line{text};

    while ((start = line.find('%')) != string::npos && (end = line.find('%', start + 1)) != string::npos) {
      auto token_str = line.substr(start, end - start + 1);

      // ignore false positives (lemonbar-style declarations)
      if (token_str[1] == '{') {
        line.erase(0, start + 1);
        continue;
      }

      line.erase(start, end - start + 1);
      tokens.emplace_back(token{token_str, 0_z, 0_z});
      auto& token = tokens.back();

      // find min delimiter
      if ((pos = token_str.find(':')) == string::npos) {
        continue;
      }

      // strip min/max specifiers from the label string token
      token.token = token_str.substr(0, pos) + '%';
      text = string_util::replace(text, token_str, token.token);

      try {
        token.min = std::stoul(&token_str[pos + 1], nullptr, 10);
      } catch (const std::invalid_argument& err) {
        continue;
      }

      // find max delimiter
      if ((pos = token_str.find(':', pos + 1)) == string::npos) {
        continue;
      }

      try {
        token.max = std::stoul(&token_str[pos + 1], nullptr, 10);
      } catch (const std::invalid_argument& err) {
        continue;
      }

      // ignore max lengths less than min
      if (token.max < token.min) {
        token.max = 0_z;
      }

      // find suffix delimiter
      if ((pos = token_str.find(':', pos + 1)) != string::npos) {
        token.suffix = token_str.substr(pos + 1);
        // remove closing token %
        token.suffix.erase(token.suffix.size() - 1);
      }
    }

    // clang-format off
    return factory_util::shared<label>(text,
        conf.get(section, name + "-foreground", ""s),
        conf.get(section, name + "-background", ""s),
        conf.get(section, name + "-underline", ""s),
        conf.get(section, name + "-overline", ""s),
        conf.get(section, name + "-font", 0),
        padding,
        margin,
        conf.get(section, name + "-maxlen", 0_z),
        conf.get(section, name + "-ellipsis", true),
        move(tokens));
    // clang-format on
  }

  /**
   * Create a label by loading optional values from the configuration
   */
  label_t load_optional_label(const config& conf, string section, string name, string def) {
    return load_label(conf, move(section), move(name), false, move(def));
  }

  /**
   * Create an icon by loading values from the configuration
   */
  icon_t load_icon(const config& conf, string section, string name, bool required, string def) {
    return load_label(conf, move(section), move(name), required, move(def));
  }

  /**
   * Create an icon by loading optional values from the configuration
   */
  icon_t load_optional_icon(const config& conf, string section, string name, string def) {
    return load_icon(conf, move(section), move(name), false, move(def));
  }
}

POLYBAR_NS_END
<|endoftext|>


<commit_before>#ifndef CINSERT_ITERATOR
#define CINSERT_ITERATOR
#include<iterator>
#include<memory>	//addressof
#include<utility>	//move

namespace nTool
{
	template<class T,class Hold,class RefFunc,class MoveFunc>
	class CInsert_iterator:public std::iterator<std::output_iterator_tag,void,void,void,void>
	{
		Hold *hold_;
		MoveFunc move_;
		RefFunc ref_;
	public:
		typedef T value_type;
		CInsert_iterator(Hold &hold,const RefFunc ref) noexcept
			:CInsert_iterator{hold,ref,ref}{}
		CInsert_iterator(Hold &hold,const RefFunc ref,const MoveFunc move) noexcept
			:hold_{std::addressof(hold)},move_{move},ref_{ref}{}
		inline CInsert_iterator& operator*() noexcept
		{
			return *this;
		}
		inline CInsert_iterator& operator++() noexcept
		{
			return *this;
		}
		inline CInsert_iterator& operator++(int) noexcept
		{
			return *this;
		}
		CInsert_iterator& operator=(const value_type &val)
		{
			(hold_->*ref_)(val);
			return *this;
		}
		CInsert_iterator& operator=(value_type &&val)
		{
			(hold_->*move_)(std::move(rVal));
			return *this;
		}
	};

	template<class T,class Hold,class RefFunc,class MoveFunc>
	inline CInsert_iterator<T,Hold,RefFunc,MoveFunc> inserter(Hold &hold,const RefFunc ref,const MoveFunc move)
	{
		return CInsert_iterator<T,Hold,RefFunc,MoveFunc>(hold,ref,move);
	}

	template<class T,class Hold,class RefFunc>
	inline CInsert_iterator<T,Hold,RefFunc,RefFunc> inserter(Hold &hold,const RefFunc ref)
	{
		return inserter<T>(hold,ref,ref);
	}
}

#endif<commit_msg>fix variable name<commit_after>#ifndef CINSERT_ITERATOR
#define CINSERT_ITERATOR
#include<iterator>
#include<memory>	//addressof
#include<utility>	//move

namespace nTool
{
	template<class T,class Hold,class RefFunc,class MoveFunc>
	class CInsert_iterator:public std::iterator<std::output_iterator_tag,void,void,void,void>
	{
		Hold *hold_;
		MoveFunc move_;
		RefFunc ref_;
	public:
		typedef T value_type;
		CInsert_iterator(Hold &hold,const RefFunc ref) noexcept
			:CInsert_iterator{hold,ref,ref}{}
		CInsert_iterator(Hold &hold,const RefFunc ref,const MoveFunc move) noexcept
			:hold_{std::addressof(hold)},move_{move},ref_{ref}{}
		inline CInsert_iterator& operator*() noexcept
		{
			return *this;
		}
		inline CInsert_iterator& operator++() noexcept
		{
			return *this;
		}
		inline CInsert_iterator& operator++(int) noexcept
		{
			return *this;
		}
		CInsert_iterator& operator=(const value_type &val)
		{
			(hold_->*ref_)(val);
			return *this;
		}
		CInsert_iterator& operator=(value_type &&rVal)
		{
			(hold_->*move_)(std::move(rVal));
			return *this;
		}
	};

	template<class T,class Hold,class RefFunc,class MoveFunc>
	inline CInsert_iterator<T,Hold,RefFunc,MoveFunc> inserter(Hold &hold,const RefFunc ref,const MoveFunc move)
	{
		return CInsert_iterator<T,Hold,RefFunc,MoveFunc>(hold,ref,move);
	}

	template<class T,class Hold,class RefFunc>
	inline CInsert_iterator<T,Hold,RefFunc,RefFunc> inserter(Hold &hold,const RefFunc ref)
	{
		return inserter<T>(hold,ref,ref);
	}
}

#endif<|endoftext|>


<commit_before>/**
* \file
* The most simple example.
* install: `yaourt -S aur/libcurlpp`
* [curlpp examples](https://github.com/jpbarrette/curlpp/tree/master/examples)
* [curlpp download wnd write callback example](https://github.com/datacratic/curlpp/blob/master/examples/example11.cpp)
* [Link errors with curlpp](http://stackoverflow.com/questions/33420631/link-errors-with-curlpp)
*/

#include <iostream>
#include <sstream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>

// curlpp specific headers
#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>

// pugixml
#include <pugixml.hpp>

// [clean html with C or C++ tidy](http://www.cppfun.com/clean-html-with-c-or-cpp-tidy.htm)
// [tidy 5.2.0-1](https://www.archlinux.org/packages/extra/x86_64/tidy/)

#include <tidy.h>
#include <buffio.h>

std::string cleanhtml(const std::string &html)
{
    // init a tidy document
    TidyDoc tidy_doc=tidyCreate();
    TidyBuffer output_buffer= {0};

    // configure tidy
    // the flags tell tidy to output xml and disable warnings
    bool config_success=tidyOptSetBool(tidy_doc,TidyXmlOut,yes)
                        && tidyOptSetBool(tidy_doc,TidyQuiet,yes)
                        && tidyOptSetBool(tidy_doc,TidyNumEntities,yes)
                        && tidyOptSetBool(tidy_doc,TidyShowWarnings,no);

    int tidy_rescode=-1;

    // parse input
    if(config_success)
        tidy_rescode=tidyParseString(tidy_doc,html.c_str());

    // process html
    if(tidy_rescode>=0)
        tidy_rescode=tidySaveBuffer(tidy_doc,&output_buffer);

    if(tidy_rescode<0)
        throw("tidy has a error: "+tidy_rescode);

    std::string result=(char *)output_buffer.bp;
    tidyBufFree(&output_buffer);
    tidyRelease(tidy_doc);

    return result;
}

using namespace curlpp::options;

bool is_ready(false);
std::mutex m;
std::condition_variable cv;

struct simple_walker: pugi::xml_tree_walker {
    virtual bool for_each(pugi::xml_node& node) {
        for (int i = 0; i < depth(); ++i) std::cout << "  "; // indentation
        std::cout << /* node_types[node.type()] << */ ": name='" << node.name() << "', value='" << node.value() << "'\n";
        return true; // continue traversal
    }
};

void
pull_one_url(std::string const& url, bool maven)
{
    //std::unique_lock<std::mutex> lk(m);
    try {
        // That's all that is needed to do cleanup of used resources (RAII style).
        curlpp::Cleanup myCleanup;

        // Our request to be sent.
        curlpp::Easy myRequest;

        // Set the URL.
        myRequest.setOpt(new curlpp::options::Url(url));
	//myRequest.setOpt(new curlpp::options::FtpListOnly(true));

        // Send request and get a result.
        // By default the result goes to standard output.

        std::ostringstream os;
        curlpp::options::WriteStream ws(&os);
        myRequest.setOpt(ws);
        myRequest.perform();
	//std::cout << "os: " << cleanhtml(os.str()) << std::endl;

        pugi::xml_document doc;
        pugi::xml_parse_result result = doc.load_string(cleanhtml(os.str()).c_str());

        if (result) {
            std::cout << "XML parsed without errors\n";
        } else {
            std::cout << "Error description: " << result.description() << "\n";
        }

        //simple_walker walker;
        //doc.traverse(walker);

        if (maven) {
            std::cout << "version name: " << doc.child("metadata").child("version").child_value() << std::endl;
            std::cout << "lastUpdated: " << doc.child("metadata").child("versioning").child("lastUpdated").child_value() << std::endl;
        } else {
            std::cout << doc.child("html").child("body").child("h1").child_value() << std::endl;
        }
    } catch(curlpp::RuntimeError & e) {
        std::cout << e.what() << std::endl;
    }

    catch(curlpp::LogicError & e) {
        std::cout << e.what() << std::endl;
    }

    is_ready = true;
    cv.notify_one();
}

int main(int, char **)
{
    std::string Url1 = "https://oss.sonatype.org/content/repositories/snapshots/edu/berkeley/cs/chisel3_2.11/";
    std::string Url2 = "https://oss.sonatype.org/content/repositories/snapshots/edu/berkeley/cs/chisel3_2.11/3.0-BETA-SNAPSHOT/maven-metadata.xml";
    std::thread t1(pull_one_url, Url1, false);
    //std::thread t2(pull_one_url, Url2, true);
    std::unique_lock<std::mutex> lk(m);
    while (!is_ready) {
        cv.wait(lk);
    }
    t1.join();
    //t2.join();

    return 0;
}

<commit_msg>a comment on installing `tidy`.<commit_after>/**
* \file
* The most simple example.
* install: `yaourt -S aur/libcurlpp`
* [curlpp examples](https://github.com/jpbarrette/curlpp/tree/master/examples)
* [curlpp download wnd write callback example](https://github.com/datacratic/curlpp/blob/master/examples/example11.cpp)
* [Link errors with curlpp](http://stackoverflow.com/questions/33420631/link-errors-with-curlpp)
*/

#include <iostream>
#include <sstream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>

// curlpp specific headers
#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>

// pugixml
#include <pugixml.hpp>

// [clean html with C or C++ tidy](http://www.cppfun.com/clean-html-with-c-or-cpp-tidy.htm)
// [tidy 5.2.0-1](https://www.archlinux.org/packages/extra/x86_64/tidy/)
// `pacman -S extra/tidy`

#include <tidy.h>
#include <buffio.h>

std::string cleanhtml(const std::string &html)
{
    // init a tidy document
    TidyDoc tidy_doc=tidyCreate();
    TidyBuffer output_buffer= {0};

    // configure tidy
    // the flags tell tidy to output xml and disable warnings
    bool config_success=tidyOptSetBool(tidy_doc,TidyXmlOut,yes)
                        && tidyOptSetBool(tidy_doc,TidyQuiet,yes)
                        && tidyOptSetBool(tidy_doc,TidyNumEntities,yes)
                        && tidyOptSetBool(tidy_doc,TidyShowWarnings,no);

    int tidy_rescode=-1;

    // parse input
    if(config_success)
        tidy_rescode=tidyParseString(tidy_doc,html.c_str());

    // process html
    if(tidy_rescode>=0)
        tidy_rescode=tidySaveBuffer(tidy_doc,&output_buffer);

    if(tidy_rescode<0)
        throw("tidy has a error: "+tidy_rescode);

    std::string result=(char *)output_buffer.bp;
    tidyBufFree(&output_buffer);
    tidyRelease(tidy_doc);

    return result;
}

using namespace curlpp::options;

bool is_ready(false);
std::mutex m;
std::condition_variable cv;

struct simple_walker: pugi::xml_tree_walker {
    virtual bool for_each(pugi::xml_node& node) {
        for (int i = 0; i < depth(); ++i) std::cout << "  "; // indentation
        std::cout << /* node_types[node.type()] << */ ": name='" << node.name() << "', value='" << node.value() << "'\n";
        return true; // continue traversal
    }
};

void
pull_one_url(std::string const& url, bool maven)
{
    //std::unique_lock<std::mutex> lk(m);
    try {
        // That's all that is needed to do cleanup of used resources (RAII style).
        curlpp::Cleanup myCleanup;

        // Our request to be sent.
        curlpp::Easy myRequest;

        // Set the URL.
        myRequest.setOpt(new curlpp::options::Url(url));
	//myRequest.setOpt(new curlpp::options::FtpListOnly(true));

        // Send request and get a result.
        // By default the result goes to standard output.

        std::ostringstream os;
        curlpp::options::WriteStream ws(&os);
        myRequest.setOpt(ws);
        myRequest.perform();
	//std::cout << "os: " << cleanhtml(os.str()) << std::endl;

        pugi::xml_document doc;
        pugi::xml_parse_result result = doc.load_string(cleanhtml(os.str()).c_str());

        if (result) {
            std::cout << "XML parsed without errors\n";
        } else {
            std::cout << "Error description: " << result.description() << "\n";
        }

        //simple_walker walker;
        //doc.traverse(walker);

        if (maven) {
            std::cout << "version name: " << doc.child("metadata").child("version").child_value() << std::endl;
            std::cout << "lastUpdated: " << doc.child("metadata").child("versioning").child("lastUpdated").child_value() << std::endl;
        } else {
            std::cout << doc.child("html").child("body").child("h1").child_value() << std::endl;
        }
    } catch(curlpp::RuntimeError & e) {
        std::cout << e.what() << std::endl;
    }

    catch(curlpp::LogicError & e) {
        std::cout << e.what() << std::endl;
    }

    is_ready = true;
    cv.notify_one();
}

int main(int, char **)
{
    std::string Url1 = "https://oss.sonatype.org/content/repositories/snapshots/edu/berkeley/cs/chisel3_2.11/";
    std::string Url2 = "https://oss.sonatype.org/content/repositories/snapshots/edu/berkeley/cs/chisel3_2.11/3.0-BETA-SNAPSHOT/maven-metadata.xml";
    std::thread t1(pull_one_url, Url1, false);
    //std::thread t2(pull_one_url, Url2, true);
    std::unique_lock<std::mutex> lk(m);
    while (!is_ready) {
        cv.wait(lk);
    }
    t1.join();
    //t2.join();

    return 0;
}

<|endoftext|>


<commit_before>#include "drake/common/have_intersection.h"

#include <vector>
#include <set>
#include "gtest/gtest.h"

using std::vector;
using std::set;

namespace drake {

namespace {

// Test using std::vector
GTEST_TEST(TestHaveIntersection, StdVectors) {
  // In order for drake::HaveIntersection to work sets must:
  // 1. Not have repeated elements.
  // 2. Be sorted.
  // An std::vector can have non sorted repeated elements. Therefore the user
  // must ensure that the previous conditions are met.
  vector<int> set1 = vector<int>({2, 9, 11, 15, 23});
  vector<int> set2 = vector<int>({9, 11, 13});
  vector<int> set3 = vector<int>({1, 8, 13});

  // set1 intersects set2 (elements 9 and 11 in common).
  EXPECT_TRUE(HaveIntersection(set1.begin(), set1.end(),
                               set2.begin(), set2.end()));

  // set2 intersects set1 (commutative).
  EXPECT_TRUE(HaveIntersection(set2.begin(), set2.end(),
                               set1.begin(), set1.end()));

  // set1 does not intersect set3 (no elements in common).
  EXPECT_FALSE(HaveIntersection(set1.begin(), set1.end(),
                                set3.begin(), set3.end()));

  // set3 does not intersect set1 (commutative).
  EXPECT_FALSE(HaveIntersection(set3.begin(), set3.end(),
                                set1.begin(), set1.end()));

  // set2 intersects set3 (element 13 in common).
  EXPECT_TRUE(HaveIntersection(set2.begin(), set2.end(),
                               set3.begin(), set3.end()));

  // set3 intersects set2 (commutative).
  EXPECT_TRUE(HaveIntersection(set3.begin(), set3.end(),
                               set2.begin(), set2.end()));
}

// Test with std::vector specific SortedVectorsHaveIntersection.
GTEST_TEST(TestHaveIntersection, SortedVectorsHaveIntersection) {
  // In order for drake::SortedVectorsHaveIntersection to work vectors must:
  // 1. Not have repeated elements.
  // 2. Be sorted.
  // An std::vector can have non sorted repeated elements. Therefore the user
  // must ensure that the previous conditions are met.
  vector<int> set1 = vector<int>({2, 9, 11, 15, 23});
  vector<int> set2 = vector<int>({9, 11, 13});
  vector<int> set3 = vector<int>({1, 8, 13});

  // set1 intersects set2 (elements 9 and 11 in common).
  EXPECT_TRUE(SortedVectorsHaveIntersection(set1, set2));

  // set2 intersects set1 (commutative).
  EXPECT_TRUE(SortedVectorsHaveIntersection(set2, set1));

  // set1 does not intersect set3 (no elements in common).
  EXPECT_FALSE(SortedVectorsHaveIntersection(set1, set3));

  // set3 does not intersect set1 (commutative).
  EXPECT_FALSE(SortedVectorsHaveIntersection(set3, set1));

  // set2 intersects set3 (element 13 in common).
  EXPECT_TRUE(SortedVectorsHaveIntersection(set2, set3));

  // set3 intersects set2 (commutative).
  EXPECT_TRUE(SortedVectorsHaveIntersection(set3, set2));
}

// Test using std::set
GTEST_TEST(TestHaveIntersection, StdSets) {
  // In order for drake::HaveIntersection to work sets must:
  // 1. Not have repeated elements.
  // 2. Be sorted.
  // std::set offers this functionality.
  set<int> set1 = set<int>({2, 9, 11, 15, 23});
  set<int> set2 = set<int>({9, 11, 13});
  set<int> set3 = set<int>({1, 8, 13});

  // Adding a previously added element to a set has no effect.
  set1.insert(11);
  set1.insert(23);

  // Elements cannot be repeated. Therefore expect 5 groups instead of 7.
  EXPECT_EQ(5, set1.size());

  // set1 intersects set2 (elements 9 and 11 in common).
  EXPECT_TRUE(HaveIntersection(set1.begin(), set1.end(),
                               set2.begin(), set2.end()));

  // set2 intersects set1 (commutative).
  EXPECT_TRUE(HaveIntersection(set2.begin(), set2.end(),
                               set1.begin(), set1.end()));

  // set1 does not intersect set3 (no elements in common).
  EXPECT_FALSE(HaveIntersection(set1.begin(), set1.end(),
                                set3.begin(), set3.end()));

  // set3 does not intersect set1 (commutative).
  EXPECT_FALSE(HaveIntersection(set3.begin(), set3.end(),
                                set1.begin(), set1.end()));

  // set2 intersects set3 (element 13 in common).
  EXPECT_TRUE(HaveIntersection(set2.begin(), set2.end(),
                               set3.begin(), set3.end()));

  // set3 intersects set2 (commutative).
  EXPECT_TRUE(HaveIntersection(set3.begin(), set3.end(),
                               set2.begin(), set2.end()));
}

}  // namespace
}  // namespace drake
<commit_msg>Added special cases tests<commit_after>#include "drake/common/have_intersection.h"

#include <vector>
#include <set>
#include "gtest/gtest.h"

using std::vector;
using std::set;

namespace drake {

namespace {

// Test using std::vector
GTEST_TEST(TestHaveIntersection, StdVectors) {
  // In order for drake::HaveIntersection to work sets must:
  // 1. Not have repeated elements.
  // 2. Be sorted.
  // An std::vector can have non sorted repeated elements. Therefore the user
  // must ensure that the previous conditions are met.
  vector<int> set1 = vector<int>({2, 9, 11, 15, 23});
  vector<int> set2 = vector<int>({9, 11, 13});
  vector<int> set3 = vector<int>({1, 8, 13});

  // set1 intersects set2 (elements 9 and 11 in common).
  EXPECT_TRUE(HaveIntersection(set1.begin(), set1.end(),
                               set2.begin(), set2.end()));

  // set2 intersects set1 (commutative).
  EXPECT_TRUE(HaveIntersection(set2.begin(), set2.end(),
                               set1.begin(), set1.end()));

  // set1 does not intersect set3 (no elements in common).
  EXPECT_FALSE(HaveIntersection(set1.begin(), set1.end(),
                                set3.begin(), set3.end()));

  // set3 does not intersect set1 (commutative).
  EXPECT_FALSE(HaveIntersection(set3.begin(), set3.end(),
                                set1.begin(), set1.end()));

  // set2 intersects set3 (element 13 in common).
  EXPECT_TRUE(HaveIntersection(set2.begin(), set2.end(),
                               set3.begin(), set3.end()));

  // set3 intersects set2 (commutative).
  EXPECT_TRUE(HaveIntersection(set3.begin(), set3.end(),
                               set2.begin(), set2.end()));

  // Empty sets.
  vector<int> set4;
  vector<int> set5;
  // Two empty sets.
  EXPECT_FALSE(HaveIntersection(set4.begin(), set4.end(),
                                set5.begin(), set5.end()));

  // First non-empty against second empty.
  EXPECT_FALSE(HaveIntersection(set1.begin(), set1.end(),
                                set4.begin(), set4.end()));

  // First empty against second non-empty.
  EXPECT_FALSE(HaveIntersection(set4.begin(), set4.end(),
                                set1.begin(), set1.end()));

  // Disjoint sets.
  vector<int> set6 = vector<int>({30, 35, 50});
  // set1 entries are all smaller than set6 first entry.
  EXPECT_FALSE(HaveIntersection(set1.begin(), set1.end(),
                                set6.begin(), set6.end()));

  // Tests if the above is commutative.
  EXPECT_FALSE(HaveIntersection(set6.begin(), set6.end(),
                                set1.begin(), set1.end()));
}

// Test with std::vector specific SortedVectorsHaveIntersection.
GTEST_TEST(TestHaveIntersection, SortedVectorsHaveIntersection) {
  // In order for drake::SortedVectorsHaveIntersection to work vectors must:
  // 1. Not have repeated elements.
  // 2. Be sorted.
  // An std::vector can have non sorted repeated elements. Therefore the user
  // must ensure that the previous conditions are met.
  vector<int> set1 = vector<int>({2, 9, 11, 15, 23});
  vector<int> set2 = vector<int>({9, 11, 13});
  vector<int> set3 = vector<int>({1, 8, 13});

  // set1 intersects set2 (elements 9 and 11 in common).
  EXPECT_TRUE(SortedVectorsHaveIntersection(set1, set2));

  // set2 intersects set1 (commutative).
  EXPECT_TRUE(SortedVectorsHaveIntersection(set2, set1));

  // set1 does not intersect set3 (no elements in common).
  EXPECT_FALSE(SortedVectorsHaveIntersection(set1, set3));

  // set3 does not intersect set1 (commutative).
  EXPECT_FALSE(SortedVectorsHaveIntersection(set3, set1));

  // set2 intersects set3 (element 13 in common).
  EXPECT_TRUE(SortedVectorsHaveIntersection(set2, set3));

  // set3 intersects set2 (commutative).
  EXPECT_TRUE(SortedVectorsHaveIntersection(set3, set2));

  // Empty sets.
  vector<int> set4;
  vector<int> set5;
  // Two empty sets.
  EXPECT_FALSE(SortedVectorsHaveIntersection(set4, set5));

  // First non-empty against second empty.
  EXPECT_FALSE(SortedVectorsHaveIntersection(set1, set4));

  // First empty against second non-empty.
  EXPECT_FALSE(SortedVectorsHaveIntersection(set4, set1));

  // Disjoint sets.
  vector<int> set6 = vector<int>({30, 35, 50});
  // set1 entries are all smaller than set6 first entry.
  EXPECT_FALSE(SortedVectorsHaveIntersection(set1, set6));

  // Tests if the above is commutative.
  EXPECT_FALSE(SortedVectorsHaveIntersection(set6, set1));
}

// Test using std::set
GTEST_TEST(TestHaveIntersection, StdSets) {
  // In order for drake::HaveIntersection to work sets must:
  // 1. Not have repeated elements.
  // 2. Be sorted.
  // std::set offers this functionality.
  set<int> set1 = set<int>({2, 9, 11, 15, 23});
  set<int> set2 = set<int>({9, 11, 13});
  set<int> set3 = set<int>({1, 8, 13});

  // Adding a previously added element to a set has no effect.
  set1.insert(11);
  set1.insert(23);

  // Elements cannot be repeated. Therefore expect 5 groups instead of 7.
  EXPECT_EQ(5, set1.size());

  // set1 intersects set2 (elements 9 and 11 in common).
  EXPECT_TRUE(HaveIntersection(set1.begin(), set1.end(),
                               set2.begin(), set2.end()));

  // set2 intersects set1 (commutative).
  EXPECT_TRUE(HaveIntersection(set2.begin(), set2.end(),
                               set1.begin(), set1.end()));

  // set1 does not intersect set3 (no elements in common).
  EXPECT_FALSE(HaveIntersection(set1.begin(), set1.end(),
                                set3.begin(), set3.end()));

  // set3 does not intersect set1 (commutative).
  EXPECT_FALSE(HaveIntersection(set3.begin(), set3.end(),
                                set1.begin(), set1.end()));

  // set2 intersects set3 (element 13 in common).
  EXPECT_TRUE(HaveIntersection(set2.begin(), set2.end(),
                               set3.begin(), set3.end()));

  // set3 intersects set2 (commutative).
  EXPECT_TRUE(HaveIntersection(set3.begin(), set3.end(),
                               set2.begin(), set2.end()));

  // Empty sets.
  set<int> set4;
  set<int> set5;
  // Two empty sets.
  EXPECT_FALSE(HaveIntersection(set4.begin(), set4.end(),
                                set5.begin(), set5.end()));

  // First non-empty against second empty.
  EXPECT_FALSE(HaveIntersection(set1.begin(), set1.end(),
                                set4.begin(), set4.end()));

  // First empty against second non-empty.
  EXPECT_FALSE(HaveIntersection(set4.begin(), set4.end(),
                                set1.begin(), set1.end()));

  // Disjoint sets.
  set<int> set6 = set<int>({30, 35, 50});
  // set1 entries are all smaller than set6 first entry.
  EXPECT_FALSE(HaveIntersection(set1.begin(), set1.end(),
                                set6.begin(), set6.end()));

  // Tests if the above is commutative.
  EXPECT_FALSE(HaveIntersection(set6.begin(), set6.end(),
                                set1.begin(), set1.end()));
}

}  // namespace
}  // namespace drake
<|endoftext|>


<commit_before>#include <getopt.h>
#include <string>
#include <math.h>

#include <boost/lexical_cast.hpp>

#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>
#include <libwatcher/client.h>
#include <libwatcher/gpsMessage.h>
#include <libwatcher/labelMessage.h>
#include <libwatcher/edgeMessage.h>
#include <libwatcher/watcherColors.h>
#include "logger.h"
#include "sendMessageHandler.h"

using namespace std;
using namespace watcher;
using namespace watcher::event;
using namespace boost;

#define PI (3.141592653589793) // Isn't this #DEFINEd somewhere?

void usage(const char *progName)
{
    fprintf(stderr, "Usage: %s [args]\n", basename(progName));
    fprintf(stderr, "Args:\n");
    fprintf(stderr, "   -s, --server=address        The addres of the node running watcherd\n");
    fprintf(stderr, "\n");
    fprintf(stderr, "Optional args:\n");
    fprintf(stderr, "   -p, --logProps              log.properties file, which controls logging for this program\n");
    fprintf(stderr, "   -r, --radius                The radius of the circle in some unknown unit\n");
    fprintf(stderr, "\n");
    fprintf(stderr, "   -h, --help                  Show this message\n");

    exit(1);
}

int main(int argc, char **argv)
{
    TRACE_ENTER();

    int c;
    string server;
    string logProps(string(basename(argv[0]))+string(".log.properties"));
    double radius=50.0;

    while (true)
    {
        int option_index = 0;
        static struct option long_options[] = {
            {"server", required_argument, 0, 's'},
            {"logProps", required_argument, 0, 'p'},
            {"radius", required_argument, 0, 'r'},
            {"help", no_argument, 0, 'h'},
            {0, 0, 0, 0}
        };

        c = getopt_long(argc, argv, "r:s:p:hH?", long_options, &option_index);

        if (c == -1)
            break;

        switch(c)
        {
            case 's':
                server=optarg;
                break;
            case 'p':
                logProps=optarg;
                break;
            case 'r':
                radius=lexical_cast<double>(optarg);
                break;
            case 'h':
            case 'H':
            case '?':
            default:
                usage(argv[0]);
                break;
        }
    }

    if (server=="")
    {
        usage(argv[0]);
        exit(1);
    }

    //
    // Now do some actual work.
    //
    LOAD_LOG_PROPS(logProps);

    Client client(server);
    LOG_INFO("Connecting to " << server << " and sending message.");
    // Do not add empty handler - default Client handler does not close connection.
    // client.addMessageHandler(SendMessageHandler::create());

    unsigned int loopTime=1;
    // Create hour, min, sec, and center nodes.
    NodeIdentifier centerId=NodeIdentifier::from_string("192.168.1.100");
    NodeIdentifier hourId=NodeIdentifier::from_string("192.168.1.101");
    NodeIdentifier minId=NodeIdentifier::from_string("192.168.1.102");
    NodeIdentifier secId=NodeIdentifier::from_string("192.168.1.103");

    const GUILayer layer("Clock");
    const double step=(2*PI)/60;
    struct
    {
        double theta;
        NodeIdentifier *id;
        const char *label;
        Color color;
        double length;
    } nodeData[]=
    {
        { 0,   &hourId, "hour", Color::red,   radius },
        { 0,    &minId,  "min", Color::blue,  radius*.8 },
        { 0,    &secId,  "sec", Color::green, radius},
    };
    while (true)  // draw everything all the time as we don't know when watcher will start
    {
        // Draw center node
        GPSMessagePtr gpsMess(new GPSMessage(radius, radius, 0));
        gpsMess->layer=layer;
        gpsMess->fromNodeID=centerId;
        if(!client.sendMessage(gpsMess))
        {
            LOG_ERROR("Error sending gps message: " << *gpsMess);
            TRACE_EXIT_RET(EXIT_FAILURE);
            return EXIT_FAILURE;
        }
        // draw hour, min, and second nodes, connecting them to center.
        for (unsigned int i=0; i<sizeof(nodeData)/sizeof(nodeData[0]); i++)
        {
            // update location offsets by current time.
            time_t nowInSecs=time(NULL);
            struct tm *now=localtime(&nowInSecs);
            if (*nodeData[i].id==hourId)
                nodeData[i].theta=step*((now->tm_hour*(60/12))+(now->tm_min/12));
            else if(*nodeData[i].id==minId)
                nodeData[i].theta=step*now->tm_min;
            else if(*nodeData[i].id==secId)
                nodeData[i].theta=step*now->tm_sec;

            // Move hour. min, and sec nodes to appropriate locations.
            GPSMessagePtr gpsMess(new GPSMessage(
                        (sin(nodeData[i].theta)*nodeData[i].length)+radius,
                        (cos(nodeData[i].theta)*nodeData[i].length)+radius,
                        (double)i));
            gpsMess->layer=layer;
            gpsMess->fromNodeID=*nodeData[i].id;
            if(!client.sendMessage(gpsMess))
            {
                LOG_ERROR("Error sending gps message: " << *gpsMess);
                TRACE_EXIT_RET(EXIT_FAILURE);
                return EXIT_FAILURE;
            }

            LabelMessagePtr labMess(new LabelMessage(nodeData[i].label));
            labMess->layer=layer;
            labMess->expiration=loopTime*2000;  // 2000 to stop blinking
            EdgeMessagePtr edgeMess(new EdgeMessage(centerId, *nodeData[i].id, layer, nodeData[i].color, 2));
            edgeMess->middleLabel=labMess;
            if(!client.sendMessage(edgeMess))
            {
                LOG_ERROR("Error sending edge message: " << *edgeMess);
                TRACE_EXIT_RET(EXIT_FAILURE);
                return EXIT_FAILURE;
            }
        }

        // add nodes at clock face number locations.
        double theta=(2*PI)/12;
        for (unsigned int i=0; i<12; i++, theta+=(2*PI)/12)
        {
            NodeIdentifier thisId=NodeIdentifier::from_string("192.168.2." + lexical_cast<string>(i+1));
            GPSMessagePtr gpsMess(new GPSMessage((sin(theta)*radius)+radius, (cos(theta)*radius)+radius, 0.0));
            gpsMess->layer=layer;
            gpsMess->fromNodeID=thisId;
            if(!client.sendMessage(gpsMess))
            {
                LOG_ERROR("Error sending gps message: " << *gpsMess);
                TRACE_EXIT_RET(EXIT_FAILURE);
                return EXIT_FAILURE;
            }
        }

        // add nodes at clock face second locations.
        theta=(2*PI)/60;
        for (unsigned int i=0; i<60; i++, theta+=(2*PI)/60)
        {
            NodeIdentifier thisId=NodeIdentifier::from_string("192.168.3." + lexical_cast<string>(i+1));
            double faceRad=radius*1.15;
            GPSMessagePtr gpsMess(new GPSMessage((sin(theta)*faceRad)+radius, (cos(theta)*faceRad)+radius, 0.0));
            gpsMess->layer=layer;
            gpsMess->fromNodeID=thisId;
            if(!client.sendMessage(gpsMess))
            {
                LOG_ERROR("Error sending gps message: " << *gpsMess);
                TRACE_EXIT_RET(EXIT_FAILURE);
                return EXIT_FAILURE;
            }
        }
        sleep(loopTime);
    }

    client.wait();

    TRACE_EXIT_RET(EXIT_SUCCESS);
    return EXIT_SUCCESS;
}

<commit_msg>showClock: added -S and -H arguments to hide the "second hand ring" and "hour hand ring".<commit_after>#include <getopt.h>
#include <string>
#include <math.h>

#include <boost/lexical_cast.hpp>

#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>
#include <libwatcher/client.h>
#include <libwatcher/gpsMessage.h>
#include <libwatcher/labelMessage.h>
#include <libwatcher/edgeMessage.h>
#include <libwatcher/watcherColors.h>
#include "logger.h"
#include "sendMessageHandler.h"

using namespace std;
using namespace watcher;
using namespace watcher::event;
using namespace boost;

#define PI (3.141592653589793) // Isn't this #DEFINEd somewhere?

void usage(const char *progName)
{
    fprintf(stderr, "Usage: %s [args]\n", basename(progName));
    fprintf(stderr, "Args:\n");
    fprintf(stderr, "   -s, --server=address        The addres of the node running watcherd\n");
    fprintf(stderr, "\n");
    fprintf(stderr, "Optional args:\n");
    fprintf(stderr, "   -p, --logProps              log.properties file, which controls logging for this program\n");
    fprintf(stderr, "   -r, --radius                The radius of the circle in some unknown unit\n");
    fprintf(stderr, "   -S, --hideSecondRing        Don't send message to draw the outer, second hand ring\n");
    fprintf(stderr, "   -H, --hideHourRing          Don't send message to draw the inner, hour hand ring\n");
    fprintf(stderr, "\n");
    fprintf(stderr, "   -h, --help                  Show this message\n");

    exit(1);
}

int main(int argc, char **argv)
{
    TRACE_ENTER();

    int c;
    string server;
    string logProps(string(basename(argv[0]))+string(".log.properties"));
    double radius=50.0;
    bool showSecondRing=true, showHourRing=true;

    while (true)
    {
        int option_index = 0;
        static struct option long_options[] = {
            {"server", required_argument, 0, 's'},
            {"logProps", required_argument, 0, 'p'},
            {"radius", no_argument, 0, 'r'},
            {"hideSecondRing", required_argument, 0, 'S'},
            {"hideHourRing", required_argument, 0, 'H'},
            {"help", no_argument, 0, 'h'},
            {0, 0, 0, 0}
        };

        c = getopt_long(argc, argv, "r:s:p:SHh?", long_options, &option_index);

        if (c == -1)
            break;

        switch(c)
        {
            case 's':
                server=optarg;
                break;
            case 'p':
                logProps=optarg;
                break;
            case 'r':
                radius=lexical_cast<double>(optarg);
                break;
            case 'S':
                showSecondRing=false;
                break;
            case 'H':
                showHourRing=false;
                break;
            case 'h':
            case '?':
            default:
                usage(argv[0]);
                break;
        }
    }

    if (server=="")
    {
        usage(argv[0]);
        exit(1);
    }

    //
    // Now do some actual work.
    //
    LOAD_LOG_PROPS(logProps);

    Client client(server);
    LOG_INFO("Connecting to " << server << " and sending message.");
    // Do not add empty handler - default Client handler does not close connection.
    // client.addMessageHandler(SendMessageHandler::create());

    unsigned int loopTime=1;
    // Create hour, min, sec, and center nodes.
    NodeIdentifier centerId=NodeIdentifier::from_string("192.168.1.100");
    NodeIdentifier hourId=NodeIdentifier::from_string("192.168.1.101");
    NodeIdentifier minId=NodeIdentifier::from_string("192.168.1.102");
    NodeIdentifier secId=NodeIdentifier::from_string("192.168.1.103");

    const GUILayer layer("Clock");
    const double step=(2*PI)/60;
    struct
    {
        double theta;
        NodeIdentifier *id;
        const char *label;
        Color color;
        double length;
    } nodeData[]=
    {
        { 0,   &hourId, "hour", Color::red,   radius },
        { 0,    &minId,  "min", Color::blue,  radius*.8 },
        { 0,    &secId,  "sec", Color::green, radius},
    };
    while (true)  // draw everything all the time as we don't know when watcher will start
    {
        // Draw center node
        GPSMessagePtr gpsMess(new GPSMessage(radius, radius, 0));
        gpsMess->layer=layer;
        gpsMess->fromNodeID=centerId;
        if(!client.sendMessage(gpsMess))
        {
            LOG_ERROR("Error sending gps message: " << *gpsMess);
            TRACE_EXIT_RET(EXIT_FAILURE);
            return EXIT_FAILURE;
        }
        // draw hour, min, and second nodes, connecting them to center.
        for (unsigned int i=0; i<sizeof(nodeData)/sizeof(nodeData[0]); i++)
        {
            // update location offsets by current time.
            time_t nowInSecs=time(NULL);
            struct tm *now=localtime(&nowInSecs);
            if (*nodeData[i].id==hourId)
                nodeData[i].theta=step*((now->tm_hour*(60/12))+(now->tm_min/12));
            else if(*nodeData[i].id==minId)
                nodeData[i].theta=step*now->tm_min;
            else if(*nodeData[i].id==secId)
                nodeData[i].theta=step*now->tm_sec;

            // Move hour. min, and sec nodes to appropriate locations.
            GPSMessagePtr gpsMess(new GPSMessage(
                        (sin(nodeData[i].theta)*nodeData[i].length)+radius,
                        (cos(nodeData[i].theta)*nodeData[i].length)+radius,
                        (double)i));
            gpsMess->layer=layer;
            gpsMess->fromNodeID=*nodeData[i].id;
            if(!client.sendMessage(gpsMess))
            {
                LOG_ERROR("Error sending gps message: " << *gpsMess);
                TRACE_EXIT_RET(EXIT_FAILURE);
                return EXIT_FAILURE;
            }

            LabelMessagePtr labMess(new LabelMessage(nodeData[i].label));
            labMess->layer=layer;
            labMess->expiration=loopTime*2000;  // 2000 to stop blinking
            EdgeMessagePtr edgeMess(new EdgeMessage(centerId, *nodeData[i].id, layer, nodeData[i].color, 2));
            edgeMess->middleLabel=labMess;
            if(!client.sendMessage(edgeMess))
            {
                LOG_ERROR("Error sending edge message: " << *edgeMess);
                TRACE_EXIT_RET(EXIT_FAILURE);
                return EXIT_FAILURE;
            }
        }

        if (showHourRing)
        {
            // add nodes at clock face number locations.
            double theta=(2*PI)/12;
            for (unsigned int i=0; i<12; i++, theta+=(2*PI)/12)
            {
                NodeIdentifier thisId=NodeIdentifier::from_string("192.168.2." + lexical_cast<string>(i+1));
                GPSMessagePtr gpsMess(new GPSMessage((sin(theta)*radius)+radius, (cos(theta)*radius)+radius, 0.0));
                gpsMess->layer=layer;
                gpsMess->fromNodeID=thisId;
                if(!client.sendMessage(gpsMess))
                {
                    LOG_ERROR("Error sending gps message: " << *gpsMess);
                    TRACE_EXIT_RET(EXIT_FAILURE);
                    return EXIT_FAILURE;
                }
            }
        }

        if (showSecondRing)
        {
            // add nodes at clock face second locations.
            double theta=(2*PI)/60;
            for (unsigned int i=0; i<60; i++, theta+=(2*PI)/60)
            {
                NodeIdentifier thisId=NodeIdentifier::from_string("192.168.3." + lexical_cast<string>(i+1));
                double faceRad=radius*1.15;
                GPSMessagePtr gpsMess(new GPSMessage((sin(theta)*faceRad)+radius, (cos(theta)*faceRad)+radius, 0.0));
                gpsMess->layer=layer;
                gpsMess->fromNodeID=thisId;
                if(!client.sendMessage(gpsMess))
                {
                    LOG_ERROR("Error sending gps message: " << *gpsMess);
                    TRACE_EXIT_RET(EXIT_FAILURE);
                    return EXIT_FAILURE;
                }
            }
        }
        sleep(loopTime);
    }

    client.wait();

    TRACE_EXIT_RET(EXIT_SUCCESS);
    return EXIT_SUCCESS;
}

<|endoftext|>