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

#include "chrome/test/ui/ui_test.h"

#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/dom_ui/new_tab_ui.h"
#include "chrome/browser/prefs/pref_value_store.h"
#include "chrome/browser/sync/signin_manager.h"
#include "chrome/common/json_pref_store.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/automation/window_proxy.h"
#include "chrome/test/testing_pref_service.h"

class NewTabUITest : public UITest {
 public:
  NewTabUITest() {
    dom_automation_enabled_ = true;
    // Set home page to the empty string so that we can set the home page using
    // preferences.
    homepage_ = "";

    // Setup the DEFAULT_THEME profile (has fake history entries).
    set_template_user_data(UITest::ComputeTypicalUserDataSource(
        UITest::DEFAULT_THEME));
  }
};

TEST_F(NewTabUITest, NTPHasThumbnails) {
  // Switch to the "new tab" tab, which should be any new tab after the
  // first (the first is about:blank).
  scoped_refptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(window.get());

  // Bring up a new tab page.
  ASSERT_TRUE(window->RunCommand(IDC_NEW_TAB));
  int load_time;
  ASSERT_TRUE(automation()->WaitForInitialNewTabUILoad(&load_time));

  scoped_refptr<TabProxy> tab = window->GetActiveTab();
  ASSERT_TRUE(tab.get());

  // TopSites should return at least 3 non-filler pages.
  // 8 - 3 = max 5 filler pages.
  ASSERT_TRUE(WaitUntilJavaScriptCondition(tab, L"",
      L"window.domAutomationController.send("
      L"document.getElementsByClassName('filler').length <= 5)",
      action_max_timeout_ms()));
}

TEST_F(NewTabUITest, NTPHasLoginName) {
  scoped_refptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(window.get());

  ASSERT_TRUE(window->SetStringPreference(prefs::kGoogleServicesUsername,
                                          "user@gmail.com"));
  // Bring up a new tab page.
  ASSERT_TRUE(window->RunCommand(IDC_NEW_TAB));
  int load_time;
  ASSERT_TRUE(automation()->WaitForInitialNewTabUILoad(&load_time));

  scoped_refptr<TabProxy> tab = window->GetActiveTab();
  ASSERT_TRUE(tab.get());

  std::wstring displayed_username;
  // The login span should be eventually populated and have the
  // correct value.
  ASSERT_TRUE(WaitUntilJavaScriptCondition(tab, L"",
      L"window.domAutomationController.send("
      L"document.getElementById('login-username').innerText.length > 0)",
      action_max_timeout_ms()));

  ASSERT_TRUE(tab->ExecuteAndExtractString(
      L"",
      L"window.domAutomationController.send("
      L"document.getElementById('login-username').innerText)",
      &displayed_username));

  EXPECT_EQ(L"user@gmail.com", displayed_username);
}

// Fails about ~5% of the time on all platforms. http://crbug.com/45001
TEST_F(NewTabUITest, FLAKY_ChromeInternalLoadsNTP) {
  scoped_refptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(window.get());

  // Go to the "new tab page" using its old url, rather than chrome://newtab.
  scoped_refptr<TabProxy> tab = window->GetTab(0);
  ASSERT_TRUE(tab.get());
  ASSERT_TRUE(tab->NavigateToURLAsync(GURL("chrome-internal:")));
  int load_time;
  ASSERT_TRUE(automation()->WaitForInitialNewTabUILoad(&load_time));

  // Ensure there are some thumbnails loaded in the page.
  int thumbnails_count = -1;
  ASSERT_TRUE(tab->ExecuteAndExtractInt(L"",
      L"window.domAutomationController.send("
      L"document.getElementsByClassName('thumbnail-container').length)",
      &thumbnails_count));
  EXPECT_GT(thumbnails_count, 0);
}

// Flaky on XP bots: http://crbug.com/51726
TEST_F(NewTabUITest, FLAKY_UpdateUserPrefsVersion) {
  // PrefService with JSON user-pref file only, no enforced or advised prefs.
  scoped_ptr<PrefService> prefs(new TestingPrefService);

  // Does the migration
  NewTabUI::RegisterUserPrefs(prefs.get());

  ASSERT_EQ(NewTabUI::current_pref_version(),
            prefs->GetInteger(prefs::kNTPPrefVersion));

  // Reset the version
  prefs->ClearPref(prefs::kNTPPrefVersion);
  ASSERT_EQ(0, prefs->GetInteger(prefs::kNTPPrefVersion));

  bool migrated = NewTabUI::UpdateUserPrefsVersion(prefs.get());
  ASSERT_TRUE(migrated);
  ASSERT_EQ(NewTabUI::current_pref_version(),
            prefs->GetInteger(prefs::kNTPPrefVersion));

  migrated = NewTabUI::UpdateUserPrefsVersion(prefs.get());
  ASSERT_FALSE(migrated);
}
<commit_msg>Marks NewTabUITest.FLAKY_NTPHasThumbnails as flaky.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/test/ui/ui_test.h"

#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/dom_ui/new_tab_ui.h"
#include "chrome/browser/prefs/pref_value_store.h"
#include "chrome/browser/sync/signin_manager.h"
#include "chrome/common/json_pref_store.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/automation/window_proxy.h"
#include "chrome/test/testing_pref_service.h"

class NewTabUITest : public UITest {
 public:
  NewTabUITest() {
    dom_automation_enabled_ = true;
    // Set home page to the empty string so that we can set the home page using
    // preferences.
    homepage_ = "";

    // Setup the DEFAULT_THEME profile (has fake history entries).
    set_template_user_data(UITest::ComputeTypicalUserDataSource(
        UITest::DEFAULT_THEME));
  }
};

// See bug 60946.
TEST_F(NewTabUITest, FLAKY_NTPHasThumbnails) {
  // Switch to the "new tab" tab, which should be any new tab after the
  // first (the first is about:blank).
  scoped_refptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(window.get());

  // Bring up a new tab page.
  ASSERT_TRUE(window->RunCommand(IDC_NEW_TAB));
  int load_time;
  ASSERT_TRUE(automation()->WaitForInitialNewTabUILoad(&load_time));

  scoped_refptr<TabProxy> tab = window->GetActiveTab();
  ASSERT_TRUE(tab.get());

  // TopSites should return at least 3 non-filler pages.
  // 8 - 3 = max 5 filler pages.
  ASSERT_TRUE(WaitUntilJavaScriptCondition(tab, L"",
      L"window.domAutomationController.send("
      L"document.getElementsByClassName('filler').length <= 5)",
      action_max_timeout_ms()));
}

TEST_F(NewTabUITest, NTPHasLoginName) {
  scoped_refptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(window.get());

  ASSERT_TRUE(window->SetStringPreference(prefs::kGoogleServicesUsername,
                                          "user@gmail.com"));
  // Bring up a new tab page.
  ASSERT_TRUE(window->RunCommand(IDC_NEW_TAB));
  int load_time;
  ASSERT_TRUE(automation()->WaitForInitialNewTabUILoad(&load_time));

  scoped_refptr<TabProxy> tab = window->GetActiveTab();
  ASSERT_TRUE(tab.get());

  std::wstring displayed_username;
  // The login span should be eventually populated and have the
  // correct value.
  ASSERT_TRUE(WaitUntilJavaScriptCondition(tab, L"",
      L"window.domAutomationController.send("
      L"document.getElementById('login-username').innerText.length > 0)",
      action_max_timeout_ms()));

  ASSERT_TRUE(tab->ExecuteAndExtractString(
      L"",
      L"window.domAutomationController.send("
      L"document.getElementById('login-username').innerText)",
      &displayed_username));

  EXPECT_EQ(L"user@gmail.com", displayed_username);
}

// Fails about ~5% of the time on all platforms. http://crbug.com/45001
TEST_F(NewTabUITest, FLAKY_ChromeInternalLoadsNTP) {
  scoped_refptr<BrowserProxy> window(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(window.get());

  // Go to the "new tab page" using its old url, rather than chrome://newtab.
  scoped_refptr<TabProxy> tab = window->GetTab(0);
  ASSERT_TRUE(tab.get());
  ASSERT_TRUE(tab->NavigateToURLAsync(GURL("chrome-internal:")));
  int load_time;
  ASSERT_TRUE(automation()->WaitForInitialNewTabUILoad(&load_time));

  // Ensure there are some thumbnails loaded in the page.
  int thumbnails_count = -1;
  ASSERT_TRUE(tab->ExecuteAndExtractInt(L"",
      L"window.domAutomationController.send("
      L"document.getElementsByClassName('thumbnail-container').length)",
      &thumbnails_count));
  EXPECT_GT(thumbnails_count, 0);
}

// Flaky on XP bots: http://crbug.com/51726
TEST_F(NewTabUITest, FLAKY_UpdateUserPrefsVersion) {
  // PrefService with JSON user-pref file only, no enforced or advised prefs.
  scoped_ptr<PrefService> prefs(new TestingPrefService);

  // Does the migration
  NewTabUI::RegisterUserPrefs(prefs.get());

  ASSERT_EQ(NewTabUI::current_pref_version(),
            prefs->GetInteger(prefs::kNTPPrefVersion));

  // Reset the version
  prefs->ClearPref(prefs::kNTPPrefVersion);
  ASSERT_EQ(0, prefs->GetInteger(prefs::kNTPPrefVersion));

  bool migrated = NewTabUI::UpdateUserPrefsVersion(prefs.get());
  ASSERT_TRUE(migrated);
  ASSERT_EQ(NewTabUI::current_pref_version(),
            prefs->GetInteger(prefs::kNTPPrefVersion));

  migrated = NewTabUI::UpdateUserPrefsVersion(prefs.get());
  ASSERT_FALSE(migrated);
}
<|endoftext|>


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

#include "base/command_line.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/automation/window_proxy.h"
#include "chrome/test/ui/ui_test.h"

namespace {

class OptionsUITest : public UITest {
 public:
  OptionsUITest() {
    dom_automation_enabled_ = true;
    // TODO(csilv): Remove when dom-ui options is enabled by default.
    launch_arguments_.AppendSwitch(switches::kEnableTabbedOptions);
  }

  void AssertIsOptionsPage(TabProxy* tab) {
    std::wstring title;
    ASSERT_TRUE(tab->GetTabTitle(&title));
    ASSERT_EQ(L"Chromium Options", title);
  }
};

TEST_F(OptionsUITest, LoadOptionsByURL) {
  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());

  scoped_refptr<TabProxy> tab = browser->GetActiveTab();
  ASSERT_TRUE(tab.get());

  // Go to the options tab via URL.
  NavigateToURL(GURL(chrome::kChromeUIOptionsURL));
  AssertIsOptionsPage(tab);
}

TEST_F(OptionsUITest, CommandOpensOptionsTab) {
  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());

  int tab_count = -1;
  ASSERT_TRUE(browser->GetTabCount(&tab_count));
  ASSERT_EQ(1, tab_count);

  // Bring up the options tab via command.
  ASSERT_TRUE(browser->RunCommand(IDC_OPTIONS));
  ASSERT_TRUE(browser->GetTabCount(&tab_count));
  ASSERT_EQ(2, tab_count);

  scoped_refptr<TabProxy> tab = browser->GetActiveTab();
  ASSERT_TRUE(tab.get());
  AssertIsOptionsPage(tab);
}

TEST_F(OptionsUITest, CommandAgainGoesBackToOptionsTab) {
  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());

  int tab_count = -1;
  ASSERT_TRUE(browser->GetTabCount(&tab_count));
  ASSERT_EQ(1, tab_count);

  // Bring up the options tab via command.
  ASSERT_TRUE(browser->RunCommand(IDC_OPTIONS));
  ASSERT_TRUE(browser->GetTabCount(&tab_count));
  ASSERT_EQ(2, tab_count);

  scoped_refptr<TabProxy> tab = browser->GetActiveTab();
  ASSERT_TRUE(tab.get());
  AssertIsOptionsPage(tab);

  // Switch to first tab and run command again.
  ASSERT_TRUE(browser->ActivateTab(0));
  ASSERT_TRUE(browser->WaitForTabToBecomeActive(0, action_max_timeout_ms()));
  ASSERT_TRUE(browser->RunCommandAsync(IDC_OPTIONS));

  // Ensure the options ui tab is active.
  ASSERT_TRUE(browser->WaitForTabToBecomeActive(1, action_max_timeout_ms()));
  ASSERT_TRUE(browser->GetTabCount(&tab_count));
  ASSERT_EQ(2, tab_count);
}

TEST_F(OptionsUITest, TwoCommandsOneTab) {
  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());

  int tab_count = -1;
  ASSERT_TRUE(browser->GetTabCount(&tab_count));
  ASSERT_EQ(1, tab_count);

  ASSERT_TRUE(browser->RunCommand(IDC_OPTIONS));
  ASSERT_TRUE(browser->RunCommandAsync(IDC_OPTIONS));
  ASSERT_TRUE(browser->GetTabCount(&tab_count));
  ASSERT_EQ(2, tab_count);
}

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

#include "base/command_line.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/automation/window_proxy.h"
#include "chrome/test/ui/ui_test.h"

namespace {

class OptionsUITest : public UITest {
 public:
  OptionsUITest() {
    dom_automation_enabled_ = true;
    // TODO(csilv): Remove when dom-ui options is enabled by default.
    launch_arguments_.AppendSwitch(switches::kEnableTabbedOptions);
  }

  void AssertIsOptionsPage(TabProxy* tab) {
    std::wstring title;
    ASSERT_TRUE(tab->GetTabTitle(&title));
    ASSERT_EQ(L"Chromium Options", title);
  }
};

TEST_F(OptionsUITest, LoadOptionsByURL) {
  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());

  scoped_refptr<TabProxy> tab = browser->GetActiveTab();
  ASSERT_TRUE(tab.get());

  // Go to the options tab via URL.
  NavigateToURL(GURL(chrome::kChromeUIOptionsURL));
  AssertIsOptionsPage(tab);
}

TEST_F(OptionsUITest, CommandOpensOptionsTab) {
  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());

  int tab_count = -1;
  ASSERT_TRUE(browser->GetTabCount(&tab_count));
  ASSERT_EQ(1, tab_count);

  // Bring up the options tab via command.
  ASSERT_TRUE(browser->RunCommand(IDC_OPTIONS));
  ASSERT_TRUE(browser->GetTabCount(&tab_count));
  ASSERT_EQ(2, tab_count);

  scoped_refptr<TabProxy> tab = browser->GetActiveTab();
  ASSERT_TRUE(tab.get());
  AssertIsOptionsPage(tab);
}

TEST_F(OptionsUITest, FAILS_CommandAgainGoesBackToOptionsTab) {
  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());

  int tab_count = -1;
  ASSERT_TRUE(browser->GetTabCount(&tab_count));
  ASSERT_EQ(1, tab_count);

  // Bring up the options tab via command.
  ASSERT_TRUE(browser->RunCommand(IDC_OPTIONS));
  ASSERT_TRUE(browser->GetTabCount(&tab_count));
  ASSERT_EQ(2, tab_count);

  scoped_refptr<TabProxy> tab = browser->GetActiveTab();
  ASSERT_TRUE(tab.get());
  AssertIsOptionsPage(tab);

  // Switch to first tab and run command again.
  ASSERT_TRUE(browser->ActivateTab(0));
  ASSERT_TRUE(browser->WaitForTabToBecomeActive(0, action_max_timeout_ms()));
  ASSERT_TRUE(browser->RunCommandAsync(IDC_OPTIONS));

  // Ensure the options ui tab is active.
  ASSERT_TRUE(browser->WaitForTabToBecomeActive(1, action_max_timeout_ms()));
  ASSERT_TRUE(browser->GetTabCount(&tab_count));
  ASSERT_EQ(2, tab_count);
}

TEST_F(OptionsUITest, TwoCommandsOneTab) {
  scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser.get());

  int tab_count = -1;
  ASSERT_TRUE(browser->GetTabCount(&tab_count));
  ASSERT_EQ(1, tab_count);

  ASSERT_TRUE(browser->RunCommand(IDC_OPTIONS));
  ASSERT_TRUE(browser->RunCommandAsync(IDC_OPTIONS));
  ASSERT_TRUE(browser->GetTabCount(&tab_count));
  ASSERT_EQ(2, tab_count);
}

}  // namespace
<|endoftext|>


<commit_before>// Copyright (c) 2009 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 <gtk/gtk.h>

#include "build/build_config.h"

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/compiler_specific.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/certificate_viewer.h"
#include "chrome/browser/gtk/gtk_util.h"
#include "chrome/browser/page_info_model.h"
#include "chrome/browser/page_info_window.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "grit/theme_resources.h"

namespace {

enum {
  RESPONSE_SHOW_CERT_INFO = 0,
};

class PageInfoWindowGtk : public PageInfoModel::PageInfoModelObserver {
 public:
  PageInfoWindowGtk(gfx::NativeWindow parent,
                    Profile* profile,
                    const GURL& url,
                    const NavigationEntry::SSLStatus& ssl,
                    bool show_history);
  ~PageInfoWindowGtk();

  // PageInfoModelObserver implementation:
  virtual void ModelChanged();

  // Shows the page info window.
  void Show();

  // Shows the certificate info window.
  void ShowCertDialog();

  GtkWidget* widget() { return dialog_; }

 private:
  // Layouts the different sections retrieved from the model.
  void InitContents();

  // Returns a widget that contains the UI for the passed |section|.
  GtkWidget* CreateSection(const PageInfoModel::SectionInfo& section);

  // The model containing the different sections to display.
  PageInfoModel model_;

  // The page info dialog.
  GtkWidget* dialog_;

  // The url for this dialog. Should be unique among active dialogs.
  GURL url_;

  // The virtual box containing the sections.
  GtkWidget* contents_;

  // The id of the certificate for this page.
  int cert_id_;

  DISALLOW_COPY_AND_ASSIGN(PageInfoWindowGtk);
};

// We only show one page info per URL (keyed on url.spec()).
typedef std::map<std::string, PageInfoWindowGtk*> PageInfoWindowMap;
PageInfoWindowMap g_page_info_window_map;

// Button callbacks.
void OnDialogResponse(GtkDialog* dialog, gint response_id,
                      PageInfoWindowGtk* page_info) {
  if (response_id == RESPONSE_SHOW_CERT_INFO) {
    page_info->ShowCertDialog();
  } else {
    // "Close" was clicked.
    gtk_widget_destroy(GTK_WIDGET(dialog));
  }
}

void OnDestroy(GtkDialog* dialog, PageInfoWindowGtk* page_info) {
  delete page_info;
}

////////////////////////////////////////////////////////////////////////////////
// PageInfoWindowGtk, public:
PageInfoWindowGtk::PageInfoWindowGtk(gfx::NativeWindow parent,
                                     Profile* profile,
                                     const GURL& url,
                                     const NavigationEntry::SSLStatus& ssl,
                                     bool show_history)
    : ALLOW_THIS_IN_INITIALIZER_LIST(model_(profile, url, ssl,
                                            show_history, this)),
      url_(url),
      contents_(NULL),
      cert_id_(ssl.cert_id()) {
  dialog_ = gtk_dialog_new_with_buttons(
      l10n_util::GetStringUTF8(IDS_PAGEINFO_WINDOW_TITLE).c_str(),
      parent,
      // Non-modal.
      GTK_DIALOG_NO_SEPARATOR,
      NULL);
  if (cert_id_) {
    gtk_dialog_add_button(
        GTK_DIALOG(dialog_),
        l10n_util::GetStringUTF8(IDS_PAGEINFO_CERT_INFO_BUTTON).c_str(),
        RESPONSE_SHOW_CERT_INFO);
  }
  gtk_dialog_add_button(GTK_DIALOG(dialog_), GTK_STOCK_CLOSE,
                        GTK_RESPONSE_CLOSE);
  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_CLOSE);

  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
                      gtk_util::kContentAreaSpacing);
  g_signal_connect(dialog_, "response", G_CALLBACK(OnDialogResponse), this);
  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnDestroy), this);

  InitContents();

  g_page_info_window_map[url.spec()] = this;
}

PageInfoWindowGtk::~PageInfoWindowGtk() {
  g_page_info_window_map.erase(url_.spec());
}

void PageInfoWindowGtk::ModelChanged() {
  InitContents();
}

GtkWidget* PageInfoWindowGtk::CreateSection(
    const PageInfoModel::SectionInfo& section) {
  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
  GtkWidget* label = gtk_label_new(UTF16ToUTF8(section.title).c_str());

  PangoAttrList* attributes = pango_attr_list_new();
  pango_attr_list_insert(attributes,
                         pango_attr_weight_new(PANGO_WEIGHT_BOLD));
  gtk_label_set_attributes(GTK_LABEL(label), attributes);
  pango_attr_list_unref(attributes);
  gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);

  GtkWidget* section_box = gtk_hbox_new(FALSE, 0);
  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  GtkWidget* image = gtk_image_new_from_pixbuf(
      section.state == PageInfoModel::SECTION_STATE_OK ?
      rb.GetPixbufNamed(IDR_PAGEINFO_GOOD) :
      rb.GetPixbufNamed(IDR_PAGEINFO_BAD));
  gtk_box_pack_start(GTK_BOX(section_box), image, FALSE, FALSE,
                     gtk_util::kControlSpacing);
  gtk_misc_set_alignment(GTK_MISC(image), 0, 0);

  GtkWidget* text_box = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
  if (!section.headline.empty()) {
    label = gtk_label_new(UTF16ToUTF8(section.headline).c_str());
    gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
    gtk_box_pack_start(GTK_BOX(text_box), label, FALSE, FALSE, 0);
  }
  label = gtk_label_new(UTF16ToUTF8(section.description).c_str());
  gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
  // Allow linebreaking in the middle of words if necessary, so that extremely
  // long hostnames (longer than one line) will still be completely shown.
  gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD_CHAR);
  gtk_box_pack_start(GTK_BOX(text_box), label, FALSE, FALSE, 0);
  gtk_widget_set_size_request(label, 400, -1);

  gtk_box_pack_start(GTK_BOX(section_box), text_box, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), section_box, TRUE, TRUE, 0);

  return vbox;
}

void PageInfoWindowGtk::InitContents() {
  if (contents_)
    gtk_widget_destroy(contents_);
  contents_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaSpacing);
  for (int i = 0; i < model_.GetSectionCount(); i++) {
    gtk_box_pack_start(GTK_BOX(contents_),
                       CreateSection(model_.GetSectionInfo(i)),
                       FALSE, FALSE, 0);
  }
  gtk_widget_show_all(contents_);
  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), contents_);
}

void PageInfoWindowGtk::Show() {
  gtk_widget_show(dialog_);
}

void PageInfoWindowGtk::ShowCertDialog() {
  ShowCertificateViewerByID(GTK_WINDOW(dialog_), cert_id_);
}

}  // namespace

namespace browser {

void ShowPageInfo(gfx::NativeWindow parent,
                  Profile* profile,
                  const GURL& url,
                  const NavigationEntry::SSLStatus& ssl,
                  bool show_history) {
  PageInfoWindowMap::iterator iter =
      g_page_info_window_map.find(url.spec());
  if (iter != g_page_info_window_map.end()) {
    gtk_window_present(GTK_WINDOW(iter->second->widget()));
    return;
  }

  PageInfoWindowGtk* page_info_window =
      new PageInfoWindowGtk(parent, profile, url, ssl, show_history);
  page_info_window->Show();
}

}  // namespace browser
<commit_msg>[gtk] Update page-info icons to match behavior in page_info_window_view.cc.<commit_after>// Copyright (c) 2009 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 <gtk/gtk.h>

#include "build/build_config.h"

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/compiler_specific.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/certificate_viewer.h"
#include "chrome/browser/gtk/gtk_util.h"
#include "chrome/browser/page_info_model.h"
#include "chrome/browser/page_info_window.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "grit/theme_resources.h"

namespace {

enum {
  RESPONSE_SHOW_CERT_INFO = 0,
};

class PageInfoWindowGtk : public PageInfoModel::PageInfoModelObserver {
 public:
  PageInfoWindowGtk(gfx::NativeWindow parent,
                    Profile* profile,
                    const GURL& url,
                    const NavigationEntry::SSLStatus& ssl,
                    bool show_history);
  ~PageInfoWindowGtk();

  // PageInfoModelObserver implementation:
  virtual void ModelChanged();

  // Shows the page info window.
  void Show();

  // Shows the certificate info window.
  void ShowCertDialog();

  GtkWidget* widget() { return dialog_; }

 private:
  // Layouts the different sections retrieved from the model.
  void InitContents();

  // Returns a widget that contains the UI for the passed |section|.
  GtkWidget* CreateSection(const PageInfoModel::SectionInfo& section);

  // The model containing the different sections to display.
  PageInfoModel model_;

  // The page info dialog.
  GtkWidget* dialog_;

  // The url for this dialog. Should be unique among active dialogs.
  GURL url_;

  // The virtual box containing the sections.
  GtkWidget* contents_;

  // The id of the certificate for this page.
  int cert_id_;

  DISALLOW_COPY_AND_ASSIGN(PageInfoWindowGtk);
};

// We only show one page info per URL (keyed on url.spec()).
typedef std::map<std::string, PageInfoWindowGtk*> PageInfoWindowMap;
PageInfoWindowMap g_page_info_window_map;

// Button callbacks.
void OnDialogResponse(GtkDialog* dialog, gint response_id,
                      PageInfoWindowGtk* page_info) {
  if (response_id == RESPONSE_SHOW_CERT_INFO) {
    page_info->ShowCertDialog();
  } else {
    // "Close" was clicked.
    gtk_widget_destroy(GTK_WIDGET(dialog));
  }
}

void OnDestroy(GtkDialog* dialog, PageInfoWindowGtk* page_info) {
  delete page_info;
}

////////////////////////////////////////////////////////////////////////////////
// PageInfoWindowGtk, public:
PageInfoWindowGtk::PageInfoWindowGtk(gfx::NativeWindow parent,
                                     Profile* profile,
                                     const GURL& url,
                                     const NavigationEntry::SSLStatus& ssl,
                                     bool show_history)
    : ALLOW_THIS_IN_INITIALIZER_LIST(model_(profile, url, ssl,
                                            show_history, this)),
      url_(url),
      contents_(NULL),
      cert_id_(ssl.cert_id()) {
  dialog_ = gtk_dialog_new_with_buttons(
      l10n_util::GetStringUTF8(IDS_PAGEINFO_WINDOW_TITLE).c_str(),
      parent,
      // Non-modal.
      GTK_DIALOG_NO_SEPARATOR,
      NULL);
  if (cert_id_) {
    gtk_dialog_add_button(
        GTK_DIALOG(dialog_),
        l10n_util::GetStringUTF8(IDS_PAGEINFO_CERT_INFO_BUTTON).c_str(),
        RESPONSE_SHOW_CERT_INFO);
  }
  gtk_dialog_add_button(GTK_DIALOG(dialog_), GTK_STOCK_CLOSE,
                        GTK_RESPONSE_CLOSE);
  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_CLOSE);

  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
                      gtk_util::kContentAreaSpacing);
  g_signal_connect(dialog_, "response", G_CALLBACK(OnDialogResponse), this);
  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnDestroy), this);

  InitContents();

  g_page_info_window_map[url.spec()] = this;
}

PageInfoWindowGtk::~PageInfoWindowGtk() {
  g_page_info_window_map.erase(url_.spec());
}

void PageInfoWindowGtk::ModelChanged() {
  InitContents();
}

GtkWidget* PageInfoWindowGtk::CreateSection(
    const PageInfoModel::SectionInfo& section) {
  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
  GtkWidget* label = gtk_label_new(UTF16ToUTF8(section.title).c_str());

  PangoAttrList* attributes = pango_attr_list_new();
  pango_attr_list_insert(attributes,
                         pango_attr_weight_new(PANGO_WEIGHT_BOLD));
  gtk_label_set_attributes(GTK_LABEL(label), attributes);
  pango_attr_list_unref(attributes);
  gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);

  GtkWidget* section_box = gtk_hbox_new(FALSE, 0);
  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  GtkWidget* image = gtk_image_new_from_pixbuf(
      section.state == PageInfoModel::SECTION_STATE_OK ?
      rb.GetPixbufNamed(IDR_PAGEINFO_GOOD) :
      rb.GetPixbufNamed(IDR_PAGEINFO_WARNING_MAJOR));
  gtk_box_pack_start(GTK_BOX(section_box), image, FALSE, FALSE,
                     gtk_util::kControlSpacing);
  gtk_misc_set_alignment(GTK_MISC(image), 0, 0);

  GtkWidget* text_box = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
  if (!section.headline.empty()) {
    label = gtk_label_new(UTF16ToUTF8(section.headline).c_str());
    gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
    gtk_box_pack_start(GTK_BOX(text_box), label, FALSE, FALSE, 0);
  }
  label = gtk_label_new(UTF16ToUTF8(section.description).c_str());
  gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
  // Allow linebreaking in the middle of words if necessary, so that extremely
  // long hostnames (longer than one line) will still be completely shown.
  gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD_CHAR);
  gtk_box_pack_start(GTK_BOX(text_box), label, FALSE, FALSE, 0);
  gtk_widget_set_size_request(label, 400, -1);

  gtk_box_pack_start(GTK_BOX(section_box), text_box, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(vbox), section_box, TRUE, TRUE, 0);

  return vbox;
}

void PageInfoWindowGtk::InitContents() {
  if (contents_)
    gtk_widget_destroy(contents_);
  contents_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaSpacing);
  for (int i = 0; i < model_.GetSectionCount(); i++) {
    gtk_box_pack_start(GTK_BOX(contents_),
                       CreateSection(model_.GetSectionInfo(i)),
                       FALSE, FALSE, 0);
  }
  gtk_widget_show_all(contents_);
  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), contents_);
}

void PageInfoWindowGtk::Show() {
  gtk_widget_show(dialog_);
}

void PageInfoWindowGtk::ShowCertDialog() {
  ShowCertificateViewerByID(GTK_WINDOW(dialog_), cert_id_);
}

}  // namespace

namespace browser {

void ShowPageInfo(gfx::NativeWindow parent,
                  Profile* profile,
                  const GURL& url,
                  const NavigationEntry::SSLStatus& ssl,
                  bool show_history) {
  PageInfoWindowMap::iterator iter =
      g_page_info_window_map.find(url.spec());
  if (iter != g_page_info_window_map.end()) {
    gtk_window_present(GTK_WINDOW(iter->second->widget()));
    return;
  }

  PageInfoWindowGtk* page_info_window =
      new PageInfoWindowGtk(parent, profile, url, ssl, show_history);
  page_info_window->Show();
}

}  // namespace browser
<|endoftext|>


<commit_before>// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s < %t.out
// RUN: %clangxx_msan -fsanitize-memory-track-origins -O3 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s < %t.out

// Test origin propagation through insertvalue IR instruction.

#include <stdio.h>
#include <stdint.h>

struct mypair {
 int64_t x;
 int y;
};

mypair my_make_pair(int64_t x, int y)  {
 mypair p;
 p.x = x;
 p.y = y;
 return p;
}

int main() {
 int64_t * volatile p = new int64_t;
 mypair z = my_make_pair(*p, 0);
 if (z.x)
   printf("zzz\n");
 // CHECK: MemorySanitizer: use-of-uninitialized-value
 // CHECK: {{in main .*insertvalue_origin.cc:}}[[@LINE-3]]

 // CHECK: Uninitialized value was created by a heap allocation
 // CHECK: {{in main .*insertvalue_origin.cc:}}[[@LINE-8]]
 delete p;
 return 0;
}
<commit_msg>Disable one MSAN test in AArch64 until we have a proper fix<commit_after>// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s < %t.out
// RUN: %clangxx_msan -fsanitize-memory-track-origins -O3 %s -o %t && not %run %t >%t.out 2>&1
// RUN: FileCheck %s < %t.out && FileCheck %s < %t.out

// Test origin propagation through insertvalue IR instruction.
// REQUIRES: stable-runtime

#include <stdio.h>
#include <stdint.h>

struct mypair {
 int64_t x;
 int y;
};

mypair my_make_pair(int64_t x, int y)  {
 mypair p;
 p.x = x;
 p.y = y;
 return p;
}

int main() {
 int64_t * volatile p = new int64_t;
 mypair z = my_make_pair(*p, 0);
 if (z.x)
   printf("zzz\n");
 // CHECK: MemorySanitizer: use-of-uninitialized-value
 // CHECK: {{in main .*insertvalue_origin.cc:}}[[@LINE-3]]

 // CHECK: Uninitialized value was created by a heap allocation
 // CHECK: {{in main .*insertvalue_origin.cc:}}[[@LINE-8]]
 delete p;
 return 0;
}
<|endoftext|>


<commit_before>/*
   Copyright (c) 2011-2017 Andreas F. Borchert
   All rights reserved.

   Permission is hereby granted, free of charge, to any person obtaining
   a copy of this software and associated documentation files (the
   "Software"), to deal in the Software without restriction, including
   without limitation the rights to use, copy, modify, merge, publish,
   distribute, sublicense, and/or sell copies of the Software, and to
   permit persons to whom the Software is furnished to do so, subject to
   the following conditions:

   The above copyright notice and this permission notice shall be
   included in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
   KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
   WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   SOFTWARE.
*/

/*
   STOP process
*/

#ifndef CSP_STOP_PROCESS_HPP
#define CSP_STOP_PROCESS_HPP

#include <cassert>
#include <iostream>
#include <memory>
#include <string>
#include "alphabet.hpp"
#include "process.hpp"

namespace CSP {

   class StopProcess: public Process {
      public:
	 StopProcess(const Alphabet& alphabet) :
	       stop_alphabet(alphabet) {
	 }
	 StopProcess(ProcessPtr p_alphabet) :
	       p_alphabet(p_alphabet) {
	 }
	 virtual void print(std::ostream& out) const {
	    out << "STOP " << get_alphabet();
	 }
	 virtual Alphabet acceptable() const {
	    return Alphabet();
	 }
      protected:
	 virtual ProcessPtr internal_proceed(std::string& next_event) {
	    return nullptr;
	 }
	 virtual Alphabet internal_get_alphabet() const {
	    if (p_alphabet) {
	       return p_alphabet->get_alphabet();
	    } else {
	       return stop_alphabet;
	    }
	 }
      private:
	 const Alphabet stop_alphabet;
	 ProcessPtr p_alphabet; // process from which we take its alphabet

	 virtual void initialize_dependencies() const {
	    p_alphabet->add_dependant(
	       std::dynamic_pointer_cast<const Process>(shared_from_this()));
	 }
   };

} // namespace CSP

#endif
<commit_msg>bug fix in stop-process.hpp: p_alphabet can be null in initialize_dependencies()<commit_after>/*
   Copyright (c) 2011-2017 Andreas F. Borchert
   All rights reserved.

   Permission is hereby granted, free of charge, to any person obtaining
   a copy of this software and associated documentation files (the
   "Software"), to deal in the Software without restriction, including
   without limitation the rights to use, copy, modify, merge, publish,
   distribute, sublicense, and/or sell copies of the Software, and to
   permit persons to whom the Software is furnished to do so, subject to
   the following conditions:

   The above copyright notice and this permission notice shall be
   included in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
   KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
   WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   SOFTWARE.
*/

/*
   STOP process
*/

#ifndef CSP_STOP_PROCESS_HPP
#define CSP_STOP_PROCESS_HPP

#include <cassert>
#include <iostream>
#include <memory>
#include <string>
#include "alphabet.hpp"
#include "process.hpp"

namespace CSP {

   class StopProcess: public Process {
      public:
	 StopProcess(const Alphabet& alphabet) :
	       stop_alphabet(alphabet) {
	 }
	 StopProcess(ProcessPtr p_alphabet) :
	       p_alphabet(p_alphabet) {
	 }
	 virtual void print(std::ostream& out) const {
	    out << "STOP " << get_alphabet();
	 }
	 virtual Alphabet acceptable() const {
	    return Alphabet();
	 }
      protected:
	 virtual ProcessPtr internal_proceed(std::string& next_event) {
	    return nullptr;
	 }
	 virtual Alphabet internal_get_alphabet() const {
	    if (p_alphabet) {
	       return p_alphabet->get_alphabet();
	    } else {
	       return stop_alphabet;
	    }
	 }
      private:
	 const Alphabet stop_alphabet;
	 ProcessPtr p_alphabet; // process from which we take its alphabet

	 virtual void initialize_dependencies() const {
	    if (p_alphabet) {
	       p_alphabet->add_dependant(
		  std::dynamic_pointer_cast<const Process>(shared_from_this()));
	    }
	 }
   };

} // namespace CSP

#endif
<|endoftext|>


<commit_before>#include "obj.h"

#include <fstream>
#include <sstream>
#include <string>
#include <cassert>
#include <array>

#include <boost/filesystem.hpp>

#include "generic_polymesh.inl"
#include "obj.h"

namespace possumwood {
namespace polymesh {

namespace {
	struct FaceIndex {
		int v = -1;
		int vn = -1;
		int vt = -1;
	};

	struct Face {
		std::vector<FaceIndex> indices;
		std::size_t objectId;
	};

	std::istream& operator >> (std::istream& in, FaceIndex& f) {
		f.v = -1;
		f.vn = -1;
		f.vt = -1;

		in >> f.v;
		if(in.peek() == '/') {
			in.get();

			if(in.peek() != '/')
				in >> f.vt;

			assert(in.peek() == '/');
			in.get();

			if(in.peek() >= '0' && in.peek() <= '9')
				in >> f.vn;

			assert(in.peek() != '/');
		}

		return in;
	}

	GenericPolymesh makeMesh(const std::vector<std::array<float, 3>>& v, const std::vector<std::array<float, 3>>& n, const std::vector<std::array<float, 2>>& uv, const std::vector<Face>& f, std::size_t indexCount) {
		GenericPolymesh result;

		// copy the vertex data
		{
			// only one per-vertex attribute - position P
			GenericPolymesh::Vertices::Handle p = result.vertices().handles().
				add<std::array<float, 3>>("P", std::array<float, 3>{{0,0,0}});

			for(auto& vert : v) {
				auto vi = result.vertices().add();
				vi->set(p, vert);
			}
		}

		// normals handle
		GenericPolymesh::Indices::Handle normalsHandle;
		if(!n.empty())
			normalsHandle = result.indices().handles().
				add<std::array<float, 3>>("N", std::array<float, 3>{{0,0,0}});

		// uv handle
		GenericPolymesh::Indices::Handle uvHandle;
		if(!n.empty())
			uvHandle = result.indices().handles().
				add<std::array<float, 2>>("uv", std::array<float, 2>{{0,0}});

		// copy the polygon data
		{
			std::vector<std::size_t> indices;
			std::vector<std::size_t> normals;
			std::vector<std::size_t> uvs;

			// only one per-polygon attribute - object ID
			GenericPolymesh::Polygons::Handle objId = result.polygons().handles().
				add<int>("objectId", 0);

			for(auto& face : f) {
				indices.clear();
				normals.clear();
				uvs.clear();

				for(auto& i : face.indices) {
					assert(i.v > 0);
					indices.push_back(i.v - 1);

					if(i.vn > 0)
						normals.push_back(i.vn - 1);

					if(i.vt > 0)
						uvs.push_back(i.vt - 1);
				}

				auto fi = result.polygons().add(indices.begin(), indices.end());
				fi->set(objId, (int)face.objectId);

				if(!normals.empty()) {
					assert(normals.size() == fi->size());

					auto ni = normals.begin();
					auto f = fi->begin();

					for(; f != fi->end(); ++f, ++ni)
						f->set(normalsHandle, n[*ni]);
				}

				if(!uvs.empty()) {
					assert(uvs.size() == fi->size());

					auto uvi = uvs.begin();
					auto f = fi->begin();

					for(; f != fi->end(); ++f, ++uvi)
						f->set(uvHandle, uv[*uvi]);
				}
			}
		}

		return result;
	}
}

GenericPolymesh loadObj(boost::filesystem::path path) {
	assert(boost::filesystem::exists(path));

	std::vector<std::array<float, 3>> vertices, normals;
	std::vector<std::array<float, 2>> uvs;
	std::vector<Face> faces;

	std::size_t vertexOrigin = 0;
	std::size_t normalOrigin = 0;
	std::size_t uvOrigin = 0;
	std::size_t objectId = 0;

	std::size_t indexCount = 0;

	std::ifstream file(path.string());

	while(!file.eof()) {
		std::string line;
		std::getline(file, line);

		if(!line.empty() && line[0] != '#') {
			std::stringstream linestr(line);

			std::string id;
			linestr >> id;

			if(id == "o") {
				if(vertices.size() != vertexOrigin || normalOrigin != normals.size()) {
					vertexOrigin = vertices.size();
					normalOrigin = normals.size();
					uvOrigin = uvs.size();

					++objectId;
				}
			}
			else if(id == "v") {
				std::array<float, 3> v;
				linestr >> v[0] >> v[1] >> v[2];

				vertices.push_back(v);
			}
			else if(id == "vn") {
				std::array<float, 3> n;
				linestr >> n[0] >> n[1] >> n[2];

				normals.push_back(n);
			}
			else if(id == "vt") {
				std::array<float, 2> t;
				linestr >> t[0] >> t[1];

				uvs.push_back(t);
			}
			else if(id == "f") {
				Face f;
				f.objectId = objectId;

				while(!linestr.eof()) {
					FaceIndex fi;
					linestr >> fi;

					if(fi.vn >= 0)
						fi.vn += normalOrigin;

					if(fi.vt > 0)
						fi.vt += uvOrigin;

					if(fi.v > 0) {
						fi.v += vertexOrigin;

						f.indices.push_back(fi);
					}
				}

				assert(f.indices.size() >= 3);
				indexCount += f.indices.size();

				faces.push_back(f);
			}
		}
	}

	return makeMesh(vertices, normals, uvs, faces, indexCount);
}

}
}
<commit_msg>Polymesh obj loading throws an exception on bad filename<commit_after>#include "obj.h"

#include <fstream>
#include <sstream>
#include <string>
#include <cassert>
#include <array>

#include <boost/filesystem.hpp>

#include "generic_polymesh.inl"
#include "obj.h"

namespace possumwood {
namespace polymesh {

namespace {
	struct FaceIndex {
		int v = -1;
		int vn = -1;
		int vt = -1;
	};

	struct Face {
		std::vector<FaceIndex> indices;
		std::size_t objectId;
	};

	std::istream& operator >> (std::istream& in, FaceIndex& f) {
		f.v = -1;
		f.vn = -1;
		f.vt = -1;

		in >> f.v;
		if(in.peek() == '/') {
			in.get();

			if(in.peek() != '/')
				in >> f.vt;

			assert(in.peek() == '/');
			in.get();

			if(in.peek() >= '0' && in.peek() <= '9')
				in >> f.vn;

			assert(in.peek() != '/');
		}

		return in;
	}

	GenericPolymesh makeMesh(const std::vector<std::array<float, 3>>& v, const std::vector<std::array<float, 3>>& n, const std::vector<std::array<float, 2>>& uv, const std::vector<Face>& f, std::size_t indexCount) {
		GenericPolymesh result;

		// copy the vertex data
		{
			// only one per-vertex attribute - position P
			GenericPolymesh::Vertices::Handle p = result.vertices().handles().
				add<std::array<float, 3>>("P", std::array<float, 3>{{0,0,0}});

			for(auto& vert : v) {
				auto vi = result.vertices().add();
				vi->set(p, vert);
			}
		}

		// normals handle
		GenericPolymesh::Indices::Handle normalsHandle;
		if(!n.empty())
			normalsHandle = result.indices().handles().
				add<std::array<float, 3>>("N", std::array<float, 3>{{0,0,0}});

		// uv handle
		GenericPolymesh::Indices::Handle uvHandle;
		if(!n.empty())
			uvHandle = result.indices().handles().
				add<std::array<float, 2>>("uv", std::array<float, 2>{{0,0}});

		// copy the polygon data
		{
			std::vector<std::size_t> indices;
			std::vector<std::size_t> normals;
			std::vector<std::size_t> uvs;

			// only one per-polygon attribute - object ID
			GenericPolymesh::Polygons::Handle objId = result.polygons().handles().
				add<int>("objectId", 0);

			for(auto& face : f) {
				indices.clear();
				normals.clear();
				uvs.clear();

				for(auto& i : face.indices) {
					assert(i.v > 0);
					indices.push_back(i.v - 1);

					if(i.vn > 0)
						normals.push_back(i.vn - 1);

					if(i.vt > 0)
						uvs.push_back(i.vt - 1);
				}

				auto fi = result.polygons().add(indices.begin(), indices.end());
				fi->set(objId, (int)face.objectId);

				if(!normals.empty()) {
					assert(normals.size() == fi->size());

					auto ni = normals.begin();
					auto f = fi->begin();

					for(; f != fi->end(); ++f, ++ni)
						f->set(normalsHandle, n[*ni]);
				}

				if(!uvs.empty()) {
					assert(uvs.size() == fi->size());

					auto uvi = uvs.begin();
					auto f = fi->begin();

					for(; f != fi->end(); ++f, ++uvi)
						f->set(uvHandle, uv[*uvi]);
				}
			}
		}

		return result;
	}
}

GenericPolymesh loadObj(boost::filesystem::path path) {
	if(!boost::filesystem::exists(path))
		throw std::runtime_error("File " + path.string() + " doesn't exist");

	std::vector<std::array<float, 3>> vertices, normals;
	std::vector<std::array<float, 2>> uvs;
	std::vector<Face> faces;

	std::size_t vertexOrigin = 0;
	std::size_t normalOrigin = 0;
	std::size_t uvOrigin = 0;
	std::size_t objectId = 0;

	std::size_t indexCount = 0;

	std::ifstream file(path.string());

	while(!file.eof()) {
		std::string line;
		std::getline(file, line);

		if(!line.empty() && line[0] != '#') {
			std::stringstream linestr(line);

			std::string id;
			linestr >> id;

			if(id == "o") {
				if(vertices.size() != vertexOrigin || normalOrigin != normals.size()) {
					vertexOrigin = vertices.size();
					normalOrigin = normals.size();
					uvOrigin = uvs.size();

					++objectId;
				}
			}
			else if(id == "v") {
				std::array<float, 3> v;
				linestr >> v[0] >> v[1] >> v[2];

				vertices.push_back(v);
			}
			else if(id == "vn") {
				std::array<float, 3> n;
				linestr >> n[0] >> n[1] >> n[2];

				normals.push_back(n);
			}
			else if(id == "vt") {
				std::array<float, 2> t;
				linestr >> t[0] >> t[1];

				uvs.push_back(t);
			}
			else if(id == "f") {
				Face f;
				f.objectId = objectId;

				while(!linestr.eof()) {
					FaceIndex fi;
					linestr >> fi;

					if(fi.vn >= 0)
						fi.vn += normalOrigin;

					if(fi.vt > 0)
						fi.vt += uvOrigin;

					if(fi.v > 0) {
						fi.v += vertexOrigin;

						f.indices.push_back(fi);
					}
				}

				assert(f.indices.size() >= 3);
				indexCount += f.indices.size();

				faces.push_back(f);
			}
		}
	}

	return makeMesh(vertices, normals, uvs, faces, indexCount);
}

}
}
<|endoftext|>


<commit_before>//
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// EXT_clip_cull_distance_test.cpp:
//   Test for EXT_clip_cull_distance
//

#include "tests/test_utils/ShaderExtensionTest.h"

namespace
{
const char EXTPragma[] = "#extension GL_EXT_clip_cull_distance : require\n";

// Shader using gl_ClipDistance and gl_CullDistance
const char VertexShaderCompileSucceeds1[] =
    R"(
    uniform vec4 uPlane;

    in vec4 aPosition;

    void main()
    {
        gl_Position = aPosition;
        gl_ClipDistance[1] = dot(aPosition, uPlane);
        gl_CullDistance[1] = dot(aPosition, uPlane);
    })";

// Shader redeclares gl_ClipDistance and gl_CullDistance
const char VertexShaderCompileSucceeds2[] =
    R"(
    uniform vec4 uPlane;

    in vec4 aPosition;

    out highp float gl_ClipDistance[4];
    out highp float gl_CullDistance[4];

    void main()
    {
        gl_Position = aPosition;
        gl_ClipDistance[gl_MaxClipDistances - 6 + 1] = dot(aPosition, uPlane);
        gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)] = dot(aPosition, uPlane);
        gl_CullDistance[gl_MaxCullDistances - 6 + 1] = dot(aPosition, uPlane);
        gl_CullDistance[gl_MaxCullDistances - int(aPosition.x)] = dot(aPosition, uPlane);
    })";

// Shader using gl_ClipDistance and gl_CullDistance
// But, the sum of the sizes is greater than gl_MaxCombinedClipAndCullDistances
const char VertexShaderCompileFails1[] =
    R"(
    uniform vec4 uPlane;

    in vec4 aPosition;

    void main()
    {
        gl_Position = aPosition;
        gl_ClipDistance[5] = dot(aPosition, uPlane);
        gl_CullDistance[4] = dot(aPosition, uPlane);
    })";

// Shader redeclares gl_ClipDistance and gl_CullDistance
// But, the sum of the sizes is greater than gl_MaxCombinedClipAndCullDistances
const char VertexShaderCompileFails2[] =
    R"(
    uniform vec4 uPlane;

    in vec4 aPosition;

    out highp float gl_ClipDistance[5];
    out highp float gl_CullDistance[4];

    void main()
    {
        gl_Position = aPosition;
        gl_ClipDistance[gl_MaxClipDistances - 6 + 1] = dot(aPosition, uPlane);
        gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)] = dot(aPosition, uPlane);
        gl_CullDistance[gl_MaxCullDistances - 6 + 1] = dot(aPosition, uPlane);
        gl_CullDistance[gl_MaxCullDistances - int(aPosition.x)] = dot(aPosition, uPlane);
    })";

// Shader redeclares gl_ClipDistance
// But, the array size is greater than gl_MaxClipDistances
const char VertexShaderCompileFails3[] =
    R"(
    uniform vec4 uPlane;

    in vec4 aPosition;

    out highp float gl_ClipDistance[gl_MaxClipDistances + 1];

    void main()
    {
        gl_Position = aPosition;
        gl_ClipDistance[gl_MaxClipDistances - 6 + 1] = dot(aPosition, uPlane);
        gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)] = dot(aPosition, uPlane);
    })";

// Access gl_CullDistance with integral constant index
// But, the index is greater than gl_MaxCullDistances
const char VertexShaderCompileFails4[] =
    R"(
    uniform vec4 uPlane;

    in vec4 aPosition;

    void main()
    {
        gl_Position = aPosition;
        gl_CullDistance[gl_MaxCullDistances] = dot(aPosition, uPlane);
    })";

const char VertexShaderCompileFails5[] =
    R"(
    uniform vec4 uPlane;

    attribute vec4 aPosition;

    void main()
    {
        gl_Position = aPosition;
        gl_CullDistance[0] = 0.0;
    })";

const char VertexShaderCompileFailes6[] =
    R"(
    uniform vec4 uPlane;

    attribute vec4 aPosition;

    varying float gl_ClipDistance[1];

    void main()
    {
        gl_Position = aPosition;
        gl_ClipDistance[0] = 0.0;
    })";

// Shader using gl_ClipDistance and gl_CullDistance
const char FragmentShaderCompileSucceeds1[] =
    R"(
    out highp vec4 fragColor;

    void main()
    {
        fragColor = vec4(gl_ClipDistance[0], gl_CullDistance[0], 0, 1);
    })";

// Shader redeclares gl_ClipDistance and gl_CullDistance
const char FragmentShaderCompileSucceeds2[] =
    R"(
    in highp float gl_ClipDistance[4];
    in highp float gl_CullDistance[4];

    in highp vec4 aPosition;

    out highp vec4 fragColor;

    void main()
    {
        fragColor.x = gl_ClipDistance[gl_MaxClipDistances - 6 + 1];
        fragColor.y = gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)];
        fragColor.z = gl_CullDistance[gl_MaxCullDistances - 6 + 1];
        fragColor.w = gl_CullDistance[gl_MaxCullDistances - int(aPosition.x)];
    })";

// Shader using gl_ClipDistance and gl_CullDistance
// But, the sum of the sizes is greater than gl_MaxCombinedClipAndCullDistances
const char FragmentShaderCompileFails1[] =
    R"(
    out highp vec4 fragColor;

    void main()
    {
        fragColor = vec4(gl_ClipDistance[4], gl_CullDistance[5], 0, 1);
    })";

// Shader redeclares gl_ClipDistance and gl_CullDistance
// But, the sum of the sizes is greater than gl_MaxCombinedClipAndCullDistances
const char FragmentShaderCompileFails2[] =
    R"(
    in highp float gl_ClipDistance[5];
    in highp float gl_CullDistance[4];

    in highp vec4 aPosition;

    out highp vec4 fragColor;

    void main()
    {
        fragColor.x = gl_ClipDistance[gl_MaxClipDistances - 6 + 1];
        fragColor.y = gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)];
        fragColor.z = gl_CullDistance[gl_MaxCullDistances - 6 + 1];
        fragColor.w = gl_CullDistance[gl_MaxCullDistances - int(aPosition.x)];
    })";

// In fragment shader, writing to gl_ClipDistance should be denied.
const char FragmentShaderCompileFails3[] =
    R"(
    out highp vec4 fragColor;

    void main()
    {
        gl_ClipDistance[0] = 0.0f;
        fragColor = vec4(1, gl_ClipDistance[0], 0, 1);
    })";

// In fragment shader, writing to gl_CullDistance should be denied even if redeclaring it with the
// array size
const char FragmentShaderCompileFails4[] =
    R"(
    out highp vec4 fragColor;

    in highp float gl_CullDistance[1];

    void main()
    {
        gl_CullDistance[0] = 0.0f;
        fragColor = vec4(1, gl_CullDistance[0], 0, 1);
    })";

// Accessing to gl_Clip/CullDistance with non-const index should be denied if the size of
// gl_Clip/CullDistance is not decided.
const char FragmentShaderCompileFails5[] =
    R"(
    out highp vec4 fragColor;

    void main()
    {
        medium float color[3];
        for(int i = 0 ; i < 3 ; i++)
        {
            color[i] = gl_CullDistance[i];
        }
        fragColor = vec4(color[0], color[1], color[2], 1.0f);
    })";

class EXTClipCullDistanceTest : public sh::ShaderExtensionTest
{
  public:
    void InitializeCompiler(ShShaderOutput shaderOutputType, GLenum shaderType)
    {
        DestroyCompiler();

        mCompiler = sh::ConstructCompiler(shaderType, testing::get<0>(GetParam()), shaderOutputType,
                                          &mResources);
        ASSERT_TRUE(mCompiler != nullptr) << "Compiler could not be constructed.";
    }

    testing::AssertionResult TestShaderCompile(const char *pragma)
    {
        const char *shaderStrings[] = {testing::get<1>(GetParam()), pragma,
                                       testing::get<2>(GetParam())};
        bool success = sh::Compile(mCompiler, shaderStrings, 3, SH_VARIABLES | SH_OBJECT_CODE);
        if (success)
        {
            return ::testing::AssertionSuccess() << "Compilation success";
        }
        return ::testing::AssertionFailure() << sh::GetInfoLog(mCompiler);
    }

    void SetExtensionEnable(bool enable)
    {
        // GL_APPLE_clip_distance is implicitly enabled when GL_EXT_clip_cull_distance is enabled
#if defined(ANGLE_ENABLE_VULKAN)
        mResources.APPLE_clip_distance = enable;
#endif
        mResources.EXT_clip_cull_distance = enable;
    }
};

class EXTClipCullDistanceForVertexShaderTest : public EXTClipCullDistanceTest
{
  public:
    void InitializeCompiler() { InitializeCompiler(SH_GLSL_450_CORE_OUTPUT); }
    void InitializeCompiler(ShShaderOutput shaderOutputType)
    {
        EXTClipCullDistanceTest::InitializeCompiler(shaderOutputType, GL_VERTEX_SHADER);
    }
};

class EXTClipCullDistanceForFragmentShaderTest : public EXTClipCullDistanceTest
{
  public:
    void InitializeCompiler() { InitializeCompiler(SH_GLSL_450_CORE_OUTPUT); }
    void InitializeCompiler(ShShaderOutput shaderOutputType)
    {
        EXTClipCullDistanceTest::InitializeCompiler(shaderOutputType, GL_FRAGMENT_SHADER);
    }
};

// Extension flag is required to compile properly. Expect failure when it is
// not present.
TEST_P(EXTClipCullDistanceForVertexShaderTest, CompileFailsWithoutExtension)
{
    SetExtensionEnable(false);
    InitializeCompiler();
    EXPECT_FALSE(TestShaderCompile(EXTPragma));
}

// Extension directive is required to compile properly. Expect failure when
// it is not present.
TEST_P(EXTClipCullDistanceForVertexShaderTest, CompileFailsWithExtensionWithoutPragma)
{
    SetExtensionEnable(true);
    InitializeCompiler();
    EXPECT_FALSE(TestShaderCompile(""));
}

#if defined(ANGLE_ENABLE_VULKAN)
// With extension flag and extension directive, compiling using TranslatorVulkan succeeds.
TEST_P(EXTClipCullDistanceForVertexShaderTest, CompileSucceedsVulkan)
{
    SetExtensionEnable(true);

    mResources.MaxClipDistances                = 8;
    mResources.MaxCullDistances                = 8;
    mResources.MaxCombinedClipAndCullDistances = 8;

    InitializeCompiler(SH_GLSL_VULKAN_OUTPUT);
    EXPECT_TRUE(TestShaderCompile(EXTPragma));
    EXPECT_FALSE(TestShaderCompile(""));
    EXPECT_TRUE(TestShaderCompile(EXTPragma));
}
#endif

// Extension flag is required to compile properly. Expect failure when it is
// not present.
TEST_P(EXTClipCullDistanceForFragmentShaderTest, CompileFailsWithoutExtension)
{
    SetExtensionEnable(false);
    InitializeCompiler();
    EXPECT_FALSE(TestShaderCompile(EXTPragma));
}

// Extension directive is required to compile properly. Expect failure when
// it is not present.
TEST_P(EXTClipCullDistanceForFragmentShaderTest, CompileFailsWithExtensionWithoutPragma)
{
    SetExtensionEnable(true);
    InitializeCompiler();
    EXPECT_FALSE(TestShaderCompile(""));
}

#if defined(ANGLE_ENABLE_VULKAN)
// With extension flag and extension directive, compiling using TranslatorVulkan succeeds.
TEST_P(EXTClipCullDistanceForFragmentShaderTest, CompileSucceedsVulkan)
{
    SetExtensionEnable(true);

    mResources.MaxClipDistances                = 8;
    mResources.MaxCullDistances                = 8;
    mResources.MaxCombinedClipAndCullDistances = 8;

    InitializeCompiler(SH_GLSL_VULKAN_OUTPUT);
    EXPECT_TRUE(TestShaderCompile(EXTPragma));
    EXPECT_FALSE(TestShaderCompile(""));
    EXPECT_TRUE(TestShaderCompile(EXTPragma));
}
#endif

class EXTClipCullDistanceForVertexShaderCompileFailureTest
    : public EXTClipCullDistanceForVertexShaderTest
{};

class EXTClipCullDistanceForFragmentShaderCompileFailureTest
    : public EXTClipCullDistanceForFragmentShaderTest
{};

#if defined(ANGLE_ENABLE_VULKAN)
TEST_P(EXTClipCullDistanceForVertexShaderCompileFailureTest, CompileFails)
{
    SetExtensionEnable(true);

    mResources.MaxClipDistances                = 8;
    mResources.MaxCullDistances                = 8;
    mResources.MaxCombinedClipAndCullDistances = 8;

    InitializeCompiler(SH_GLSL_VULKAN_OUTPUT);
    EXPECT_FALSE(TestShaderCompile(EXTPragma));
}

TEST_P(EXTClipCullDistanceForFragmentShaderCompileFailureTest, CompileFails)
{
    SetExtensionEnable(true);

    mResources.MaxClipDistances                = 8;
    mResources.MaxCullDistances                = 8;
    mResources.MaxCombinedClipAndCullDistances = 8;

    InitializeCompiler(SH_GLSL_VULKAN_OUTPUT);
    EXPECT_FALSE(TestShaderCompile(EXTPragma));
}
#endif

INSTANTIATE_TEST_SUITE_P(IncorrectESSL100Shaders,
                         EXTClipCullDistanceForVertexShaderCompileFailureTest,
                         Combine(Values(SH_GLES2_SPEC),
                                 Values(sh::ESSLVersion100),
                                 Values(VertexShaderCompileFails5, VertexShaderCompileFailes6)));

INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders,
                         EXTClipCullDistanceForVertexShaderTest,
                         Combine(Values(SH_GLES3_SPEC),
                                 Values(sh::ESSLVersion300),
                                 Values(VertexShaderCompileSucceeds1,
                                        VertexShaderCompileSucceeds2)));

INSTANTIATE_TEST_SUITE_P(IncorrectESSL300Shaders,
                         EXTClipCullDistanceForVertexShaderCompileFailureTest,
                         Combine(Values(SH_GLES3_SPEC),
                                 Values(sh::ESSLVersion300),
                                 Values(VertexShaderCompileFails1,
                                        VertexShaderCompileFails2,
                                        VertexShaderCompileFails3,
                                        VertexShaderCompileFails4)));

INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders,
                         EXTClipCullDistanceForFragmentShaderTest,
                         Combine(Values(SH_GLES3_SPEC),
                                 Values(sh::ESSLVersion300),
                                 Values(FragmentShaderCompileSucceeds1,
                                        FragmentShaderCompileSucceeds2)));

INSTANTIATE_TEST_SUITE_P(IncorrectESSL300Shaders,
                         EXTClipCullDistanceForFragmentShaderCompileFailureTest,
                         Combine(Values(SH_GLES3_SPEC),
                                 Values(sh::ESSLVersion300),
                                 Values(FragmentShaderCompileFails1,
                                        FragmentShaderCompileFails2,
                                        FragmentShaderCompileFails3,
                                        FragmentShaderCompileFails4,
                                        FragmentShaderCompileFails5)));

}  // anonymous namespace
<commit_msg>Only define test suites when TEST_Ps defined<commit_after>//
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// EXT_clip_cull_distance_test.cpp:
//   Test for EXT_clip_cull_distance
//

#include "tests/test_utils/ShaderExtensionTest.h"

namespace
{
const char EXTPragma[] = "#extension GL_EXT_clip_cull_distance : require\n";

// Shader using gl_ClipDistance and gl_CullDistance
const char VertexShaderCompileSucceeds1[] =
    R"(
    uniform vec4 uPlane;

    in vec4 aPosition;

    void main()
    {
        gl_Position = aPosition;
        gl_ClipDistance[1] = dot(aPosition, uPlane);
        gl_CullDistance[1] = dot(aPosition, uPlane);
    })";

// Shader redeclares gl_ClipDistance and gl_CullDistance
const char VertexShaderCompileSucceeds2[] =
    R"(
    uniform vec4 uPlane;

    in vec4 aPosition;

    out highp float gl_ClipDistance[4];
    out highp float gl_CullDistance[4];

    void main()
    {
        gl_Position = aPosition;
        gl_ClipDistance[gl_MaxClipDistances - 6 + 1] = dot(aPosition, uPlane);
        gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)] = dot(aPosition, uPlane);
        gl_CullDistance[gl_MaxCullDistances - 6 + 1] = dot(aPosition, uPlane);
        gl_CullDistance[gl_MaxCullDistances - int(aPosition.x)] = dot(aPosition, uPlane);
    })";

#if defined(ANGLE_ENABLE_VULKAN)
// Shader using gl_ClipDistance and gl_CullDistance
// But, the sum of the sizes is greater than gl_MaxCombinedClipAndCullDistances
const char VertexShaderCompileFails1[] =
    R"(
    uniform vec4 uPlane;

    in vec4 aPosition;

    void main()
    {
        gl_Position = aPosition;
        gl_ClipDistance[5] = dot(aPosition, uPlane);
        gl_CullDistance[4] = dot(aPosition, uPlane);
    })";

// Shader redeclares gl_ClipDistance and gl_CullDistance
// But, the sum of the sizes is greater than gl_MaxCombinedClipAndCullDistances
const char VertexShaderCompileFails2[] =
    R"(
    uniform vec4 uPlane;

    in vec4 aPosition;

    out highp float gl_ClipDistance[5];
    out highp float gl_CullDistance[4];

    void main()
    {
        gl_Position = aPosition;
        gl_ClipDistance[gl_MaxClipDistances - 6 + 1] = dot(aPosition, uPlane);
        gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)] = dot(aPosition, uPlane);
        gl_CullDistance[gl_MaxCullDistances - 6 + 1] = dot(aPosition, uPlane);
        gl_CullDistance[gl_MaxCullDistances - int(aPosition.x)] = dot(aPosition, uPlane);
    })";

// Shader redeclares gl_ClipDistance
// But, the array size is greater than gl_MaxClipDistances
const char VertexShaderCompileFails3[] =
    R"(
    uniform vec4 uPlane;

    in vec4 aPosition;

    out highp float gl_ClipDistance[gl_MaxClipDistances + 1];

    void main()
    {
        gl_Position = aPosition;
        gl_ClipDistance[gl_MaxClipDistances - 6 + 1] = dot(aPosition, uPlane);
        gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)] = dot(aPosition, uPlane);
    })";

// Access gl_CullDistance with integral constant index
// But, the index is greater than gl_MaxCullDistances
const char VertexShaderCompileFails4[] =
    R"(
    uniform vec4 uPlane;

    in vec4 aPosition;

    void main()
    {
        gl_Position = aPosition;
        gl_CullDistance[gl_MaxCullDistances] = dot(aPosition, uPlane);
    })";

const char VertexShaderCompileFails5[] =
    R"(
    uniform vec4 uPlane;

    attribute vec4 aPosition;

    void main()
    {
        gl_Position = aPosition;
        gl_CullDistance[0] = 0.0;
    })";

const char VertexShaderCompileFailes6[] =
    R"(
    uniform vec4 uPlane;

    attribute vec4 aPosition;

    varying float gl_ClipDistance[1];

    void main()
    {
        gl_Position = aPosition;
        gl_ClipDistance[0] = 0.0;
    })";
#endif

// Shader using gl_ClipDistance and gl_CullDistance
const char FragmentShaderCompileSucceeds1[] =
    R"(
    out highp vec4 fragColor;

    void main()
    {
        fragColor = vec4(gl_ClipDistance[0], gl_CullDistance[0], 0, 1);
    })";

// Shader redeclares gl_ClipDistance and gl_CullDistance
const char FragmentShaderCompileSucceeds2[] =
    R"(
    in highp float gl_ClipDistance[4];
    in highp float gl_CullDistance[4];

    in highp vec4 aPosition;

    out highp vec4 fragColor;

    void main()
    {
        fragColor.x = gl_ClipDistance[gl_MaxClipDistances - 6 + 1];
        fragColor.y = gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)];
        fragColor.z = gl_CullDistance[gl_MaxCullDistances - 6 + 1];
        fragColor.w = gl_CullDistance[gl_MaxCullDistances - int(aPosition.x)];
    })";

#if defined(ANGLE_ENABLE_VULKAN)
// Shader using gl_ClipDistance and gl_CullDistance
// But, the sum of the sizes is greater than gl_MaxCombinedClipAndCullDistances
const char FragmentShaderCompileFails1[] =
    R"(
    out highp vec4 fragColor;

    void main()
    {
        fragColor = vec4(gl_ClipDistance[4], gl_CullDistance[5], 0, 1);
    })";

// Shader redeclares gl_ClipDistance and gl_CullDistance
// But, the sum of the sizes is greater than gl_MaxCombinedClipAndCullDistances
const char FragmentShaderCompileFails2[] =
    R"(
    in highp float gl_ClipDistance[5];
    in highp float gl_CullDistance[4];

    in highp vec4 aPosition;

    out highp vec4 fragColor;

    void main()
    {
        fragColor.x = gl_ClipDistance[gl_MaxClipDistances - 6 + 1];
        fragColor.y = gl_ClipDistance[gl_MaxClipDistances - int(aPosition.x)];
        fragColor.z = gl_CullDistance[gl_MaxCullDistances - 6 + 1];
        fragColor.w = gl_CullDistance[gl_MaxCullDistances - int(aPosition.x)];
    })";

// In fragment shader, writing to gl_ClipDistance should be denied.
const char FragmentShaderCompileFails3[] =
    R"(
    out highp vec4 fragColor;

    void main()
    {
        gl_ClipDistance[0] = 0.0f;
        fragColor = vec4(1, gl_ClipDistance[0], 0, 1);
    })";

// In fragment shader, writing to gl_CullDistance should be denied even if redeclaring it with the
// array size
const char FragmentShaderCompileFails4[] =
    R"(
    out highp vec4 fragColor;

    in highp float gl_CullDistance[1];

    void main()
    {
        gl_CullDistance[0] = 0.0f;
        fragColor = vec4(1, gl_CullDistance[0], 0, 1);
    })";

// Accessing to gl_Clip/CullDistance with non-const index should be denied if the size of
// gl_Clip/CullDistance is not decided.
const char FragmentShaderCompileFails5[] =
    R"(
    out highp vec4 fragColor;

    void main()
    {
        medium float color[3];
        for(int i = 0 ; i < 3 ; i++)
        {
            color[i] = gl_CullDistance[i];
        }
        fragColor = vec4(color[0], color[1], color[2], 1.0f);
    })";
#endif

class EXTClipCullDistanceTest : public sh::ShaderExtensionTest
{
  public:
    void InitializeCompiler(ShShaderOutput shaderOutputType, GLenum shaderType)
    {
        DestroyCompiler();

        mCompiler = sh::ConstructCompiler(shaderType, testing::get<0>(GetParam()), shaderOutputType,
                                          &mResources);
        ASSERT_TRUE(mCompiler != nullptr) << "Compiler could not be constructed.";
    }

    testing::AssertionResult TestShaderCompile(const char *pragma)
    {
        const char *shaderStrings[] = {testing::get<1>(GetParam()), pragma,
                                       testing::get<2>(GetParam())};
        bool success = sh::Compile(mCompiler, shaderStrings, 3, SH_VARIABLES | SH_OBJECT_CODE);
        if (success)
        {
            return ::testing::AssertionSuccess() << "Compilation success";
        }
        return ::testing::AssertionFailure() << sh::GetInfoLog(mCompiler);
    }

    void SetExtensionEnable(bool enable)
    {
        // GL_APPLE_clip_distance is implicitly enabled when GL_EXT_clip_cull_distance is enabled
#if defined(ANGLE_ENABLE_VULKAN)
        mResources.APPLE_clip_distance = enable;
#endif
        mResources.EXT_clip_cull_distance = enable;
    }
};

class EXTClipCullDistanceForVertexShaderTest : public EXTClipCullDistanceTest
{
  public:
    void InitializeCompiler() { InitializeCompiler(SH_GLSL_450_CORE_OUTPUT); }
    void InitializeCompiler(ShShaderOutput shaderOutputType)
    {
        EXTClipCullDistanceTest::InitializeCompiler(shaderOutputType, GL_VERTEX_SHADER);
    }
};

class EXTClipCullDistanceForFragmentShaderTest : public EXTClipCullDistanceTest
{
  public:
    void InitializeCompiler() { InitializeCompiler(SH_GLSL_450_CORE_OUTPUT); }
    void InitializeCompiler(ShShaderOutput shaderOutputType)
    {
        EXTClipCullDistanceTest::InitializeCompiler(shaderOutputType, GL_FRAGMENT_SHADER);
    }
};

// Extension flag is required to compile properly. Expect failure when it is
// not present.
TEST_P(EXTClipCullDistanceForVertexShaderTest, CompileFailsWithoutExtension)
{
    SetExtensionEnable(false);
    InitializeCompiler();
    EXPECT_FALSE(TestShaderCompile(EXTPragma));
}

// Extension directive is required to compile properly. Expect failure when
// it is not present.
TEST_P(EXTClipCullDistanceForVertexShaderTest, CompileFailsWithExtensionWithoutPragma)
{
    SetExtensionEnable(true);
    InitializeCompiler();
    EXPECT_FALSE(TestShaderCompile(""));
}

#if defined(ANGLE_ENABLE_VULKAN)
// With extension flag and extension directive, compiling using TranslatorVulkan succeeds.
TEST_P(EXTClipCullDistanceForVertexShaderTest, CompileSucceedsVulkan)
{
    SetExtensionEnable(true);

    mResources.MaxClipDistances                = 8;
    mResources.MaxCullDistances                = 8;
    mResources.MaxCombinedClipAndCullDistances = 8;

    InitializeCompiler(SH_GLSL_VULKAN_OUTPUT);
    EXPECT_TRUE(TestShaderCompile(EXTPragma));
    EXPECT_FALSE(TestShaderCompile(""));
    EXPECT_TRUE(TestShaderCompile(EXTPragma));
}
#endif

// Extension flag is required to compile properly. Expect failure when it is
// not present.
TEST_P(EXTClipCullDistanceForFragmentShaderTest, CompileFailsWithoutExtension)
{
    SetExtensionEnable(false);
    InitializeCompiler();
    EXPECT_FALSE(TestShaderCompile(EXTPragma));
}

// Extension directive is required to compile properly. Expect failure when
// it is not present.
TEST_P(EXTClipCullDistanceForFragmentShaderTest, CompileFailsWithExtensionWithoutPragma)
{
    SetExtensionEnable(true);
    InitializeCompiler();
    EXPECT_FALSE(TestShaderCompile(""));
}

#if defined(ANGLE_ENABLE_VULKAN)
// With extension flag and extension directive, compiling using TranslatorVulkan succeeds.
TEST_P(EXTClipCullDistanceForFragmentShaderTest, CompileSucceedsVulkan)
{
    SetExtensionEnable(true);

    mResources.MaxClipDistances                = 8;
    mResources.MaxCullDistances                = 8;
    mResources.MaxCombinedClipAndCullDistances = 8;

    InitializeCompiler(SH_GLSL_VULKAN_OUTPUT);
    EXPECT_TRUE(TestShaderCompile(EXTPragma));
    EXPECT_FALSE(TestShaderCompile(""));
    EXPECT_TRUE(TestShaderCompile(EXTPragma));
}

class EXTClipCullDistanceForVertexShaderCompileFailureTest
    : public EXTClipCullDistanceForVertexShaderTest
{};

class EXTClipCullDistanceForFragmentShaderCompileFailureTest
    : public EXTClipCullDistanceForFragmentShaderTest
{};

TEST_P(EXTClipCullDistanceForVertexShaderCompileFailureTest, CompileFails)
{
    SetExtensionEnable(true);

    mResources.MaxClipDistances                = 8;
    mResources.MaxCullDistances                = 8;
    mResources.MaxCombinedClipAndCullDistances = 8;

    InitializeCompiler(SH_GLSL_VULKAN_OUTPUT);
    EXPECT_FALSE(TestShaderCompile(EXTPragma));
}

TEST_P(EXTClipCullDistanceForFragmentShaderCompileFailureTest, CompileFails)
{
    SetExtensionEnable(true);

    mResources.MaxClipDistances                = 8;
    mResources.MaxCullDistances                = 8;
    mResources.MaxCombinedClipAndCullDistances = 8;

    InitializeCompiler(SH_GLSL_VULKAN_OUTPUT);
    EXPECT_FALSE(TestShaderCompile(EXTPragma));
}
#endif

INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders,
                         EXTClipCullDistanceForVertexShaderTest,
                         Combine(Values(SH_GLES3_SPEC),
                                 Values(sh::ESSLVersion300),
                                 Values(VertexShaderCompileSucceeds1,
                                        VertexShaderCompileSucceeds2)));

INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders,
                         EXTClipCullDistanceForFragmentShaderTest,
                         Combine(Values(SH_GLES3_SPEC),
                                 Values(sh::ESSLVersion300),
                                 Values(FragmentShaderCompileSucceeds1,
                                        FragmentShaderCompileSucceeds2)));

// The corresponding TEST_Ps are defined only when ANGLE_ENABLE_VULKAN is
// defined.
#if defined(ANGLE_ENABLE_VULKAN)
INSTANTIATE_TEST_SUITE_P(IncorrectESSL100Shaders,
                         EXTClipCullDistanceForVertexShaderCompileFailureTest,
                         Combine(Values(SH_GLES2_SPEC),
                                 Values(sh::ESSLVersion100),
                                 Values(VertexShaderCompileFails5, VertexShaderCompileFailes6)));

INSTANTIATE_TEST_SUITE_P(IncorrectESSL300Shaders,
                         EXTClipCullDistanceForVertexShaderCompileFailureTest,
                         Combine(Values(SH_GLES3_SPEC),
                                 Values(sh::ESSLVersion300),
                                 Values(VertexShaderCompileFails1,
                                        VertexShaderCompileFails2,
                                        VertexShaderCompileFails3,
                                        VertexShaderCompileFails4)));

INSTANTIATE_TEST_SUITE_P(IncorrectESSL300Shaders,
                         EXTClipCullDistanceForFragmentShaderCompileFailureTest,
                         Combine(Values(SH_GLES3_SPEC),
                                 Values(sh::ESSLVersion300),
                                 Values(FragmentShaderCompileFails1,
                                        FragmentShaderCompileFails2,
                                        FragmentShaderCompileFails3,
                                        FragmentShaderCompileFails4,
                                        FragmentShaderCompileFails5)));
#endif

}  // anonymous namespace
<|endoftext|>


<commit_before>// @(#)root/reflex:$Id$
// Author: Stefan Roiser 2004

// Copyright CERN, CH-1211 Geneva 23, 2004-2006, All rights reserved.
//
// Permission to use, copy, modify, and distribute this software for any
// purpose is hereby granted without fee, provided that this copyright and
// permissions notice appear in all copies and derivatives.
//
// This software is provided "as is" without express or implied warranty.

#ifndef REFLEX_BUILD
#define REFLEX_BUILD
#endif

#include "Reflex/Base.h"
#include "Class.h"

//-------------------------------------------------------------------------------
Reflex::Base::Base( const Type &    baseType,
                          OffsetFunction  offsetfp,
                          unsigned int    modifiers )
   : fOffsetFP( offsetfp ),
     fModifiers( modifiers ),
     fBaseType( Type() ),
     fBaseClass( 0 ) {
//-------------------------------------------------------------------------------
// Construct the information for a base. The pointer to the base class (type Class)
// is set to 0 initially and set on first access.
   fBaseType = baseType;
}

//-------------------------------------------------------------------------------
const Reflex::Class * Reflex::Base::BaseClass() const {
//-------------------------------------------------------------------------------
// Return the pointer to the base class. Set on first access.
   if ( fBaseClass ) return fBaseClass;
   if ( fBaseType ) {
      fBaseClass = dynamic_cast< const Class * >(fBaseType.ToTypeBase());
      return fBaseClass;
   }
   return 0;
}

//-------------------------------------------------------------------------------
std::string Reflex::Base::Name( unsigned int mod ) const {
//-------------------------------------------------------------------------------
// Construct the name of the base. Qualify if requested.
   std::string s = "";
   if ( 0 != ( mod & ( QUALIFIED | Q ))) {
      if ( IsPublic())    { s += "public "; }
      if ( IsProtected()) { s += "protected "; }
      if ( IsPrivate())   { s += "private "; }
      if ( IsVirtual())   { s += "virtual "; }
   }
   s += fBaseType.Name( mod );
   return s;
}
<commit_msg>remove unnecessary assignment of empty string<commit_after>// @(#)root/reflex:$Id$
// Author: Stefan Roiser 2004

// Copyright CERN, CH-1211 Geneva 23, 2004-2006, All rights reserved.
//
// Permission to use, copy, modify, and distribute this software for any
// purpose is hereby granted without fee, provided that this copyright and
// permissions notice appear in all copies and derivatives.
//
// This software is provided "as is" without express or implied warranty.

#ifndef REFLEX_BUILD
#define REFLEX_BUILD
#endif

#include "Reflex/Base.h"
#include "Class.h"

//-------------------------------------------------------------------------------
Reflex::Base::Base( const Type &    baseType,
                          OffsetFunction  offsetfp,
                          unsigned int    modifiers )
   : fOffsetFP( offsetfp ),
     fModifiers( modifiers ),
     fBaseType( Type() ),
     fBaseClass( 0 ) {
//-------------------------------------------------------------------------------
// Construct the information for a base. The pointer to the base class (type Class)
// is set to 0 initially and set on first access.
   fBaseType = baseType;
}

//-------------------------------------------------------------------------------
const Reflex::Class * Reflex::Base::BaseClass() const {
//-------------------------------------------------------------------------------
// Return the pointer to the base class. Set on first access.
   if ( fBaseClass ) return fBaseClass;
   if ( fBaseType ) {
      fBaseClass = dynamic_cast< const Class * >(fBaseType.ToTypeBase());
      return fBaseClass;
   }
   return 0;
}

//-------------------------------------------------------------------------------
std::string Reflex::Base::Name( unsigned int mod ) const {
//-------------------------------------------------------------------------------
// Construct the name of the base. Qualify if requested.
   std::string s;
   if ( 0 != ( mod & ( QUALIFIED | Q ))) {
      if ( IsPublic())    { s += "public "; }
      if ( IsProtected()) { s += "protected "; }
      if ( IsPrivate())   { s += "private "; }
      if ( IsVirtual())   { s += "virtual "; }
   }
   s += fBaseType.Name( mod );
   return s;
}
<|endoftext|>


<commit_before>#include "VTrailArea.h"
#include "VGlobal.h"

VTrailArea::VTrailArea(float x, float y, unsigned int width, unsigned int height, unsigned int maxSize) : VRenderGroup(x, y, width, height, maxSize)
{
	renderTex.clear(sf::Color::Transparent);
}

VTrailArea::VTrailArea(sf::Vector2f position, sf::Vector2u size, unsigned int maxSize) : VRenderGroup(position, size, maxSize)
{
	renderTex.clear(sf::Color::Transparent);
}

void VTrailArea::Draw(sf::RenderTarget& RenderTarget)
{
	float time = fadeTimer.getElapsedTime().asSeconds();
	if (time > Delay)
	{
		sf::View renderTexView = renderTex.getView();
		renderTex.setView(renderTex.getDefaultView());
		trailTexture = sf::Texture(renderTex.getTexture());
		trailSprite.setTexture(trailTexture);
		trailSprite.setPosition(lastPos.x - Sprite->Position.x, lastPos.y - Sprite->Position.y);
		trailSprite.setColor(
			sf::Color(
				255 - sf::Uint8(255 * RedMultiplier   * time),
				255 - sf::Uint8(255 * GreenMultiplier * time),
				255 - sf::Uint8(255 * BlueMultiplier  * time),
				255 - sf::Uint8(255 * AlphaMultiplier * time)
			)
		);
		renderTex.clear(sf::Color::Transparent);
		renderTex.draw(trailSprite);
		renderTex.setView(renderTexView);
		VGroup::Draw(renderTex);
		renderTex.display();
		fadeTimer.restart();

		lastPos = Sprite->Position;
	}

	if (PostEffect != nullptr && VPostEffectBase::isSupported())
	{
		if (postProcessTex.getSize().x == 0 || postProcessTex.getSize().y == 0)
		{
			postProcessTex.create(renderTex.getSize().x, renderTex.getSize().y);
		}

		postProcessTex.clear(sf::Color::Transparent);
		PostEffect->Apply(renderTex.getTexture(), postProcessTex);
		postProcessTex.display();

		updateTexture(postProcessTex.getTexture());
	}
	else
	{
		updateTexture(renderTex.getTexture());
	}

	Sprite->RenderState.blendMode = sf::BlendAdd;
	Sprite->Draw(RenderTarget);

	if (RenderOutside)
		VGroup::Draw(RenderTarget);
}<commit_msg>Move update transform to draw<commit_after>#include "VTrailArea.h"
#include "VGlobal.h"

VTrailArea::VTrailArea(float x, float y, unsigned int width, unsigned int height, unsigned int maxSize) : VRenderGroup(x, y, width, height, maxSize)
{
	renderTex.clear(sf::Color::Transparent);
}

VTrailArea::VTrailArea(sf::Vector2f position, sf::Vector2u size, unsigned int maxSize) : VRenderGroup(position, size, maxSize)
{
	renderTex.clear(sf::Color::Transparent);
}

void VTrailArea::Draw(sf::RenderTarget& RenderTarget)
{
	updateTransform();

	float time = fadeTimer.getElapsedTime().asSeconds();
	if (time > Delay)
	{
		sf::View renderTexView = renderTex.getView();
		renderTex.setView(renderTex.getDefaultView());
		trailTexture = sf::Texture(renderTex.getTexture());
		trailSprite.setTexture(trailTexture);
		trailSprite.setPosition(lastPos.x - Sprite->Position.x, lastPos.y - Sprite->Position.y);
		trailSprite.setColor(
			sf::Color(
				255 - sf::Uint8(255 * RedMultiplier   * time),
				255 - sf::Uint8(255 * GreenMultiplier * time),
				255 - sf::Uint8(255 * BlueMultiplier  * time),
				255 - sf::Uint8(255 * AlphaMultiplier * time)
			)
		);
		renderTex.clear(sf::Color::Transparent);
		renderTex.draw(trailSprite);
		renderTex.setView(renderTexView);
		VGroup::Draw(renderTex);
		renderTex.display();
		fadeTimer.restart();

		lastPos = Sprite->Position;
	}

	if (PostEffect != nullptr && VPostEffectBase::isSupported())
	{
		if (postProcessTex.getSize().x == 0 || postProcessTex.getSize().y == 0)
		{
			postProcessTex.create(renderTex.getSize().x, renderTex.getSize().y);
		}

		postProcessTex.clear(sf::Color::Transparent);
		PostEffect->Apply(renderTex.getTexture(), postProcessTex);
		postProcessTex.display();

		updateTexture(postProcessTex.getTexture());
	}
	else
	{
		updateTexture(renderTex.getTexture());
	}

	Sprite->RenderState.blendMode = sf::BlendAdd;
	Sprite->Draw(RenderTarget);

	if (RenderOutside)
		VGroup::Draw(RenderTarget);
}<|endoftext|>


<commit_before>/*
* socket-server
*
* Simple socket server implementation based on poll()
* 2015 Yuzo(Huang Yuzhong)
*
* Server program arch:
* 		Master thread: Use poll() to handle multiple client.
*/

#ifdef _WIN32
	#define _CRT_SECURE_NO_WARNINGS
	#define _WINSOCK_DEPRECATED_NO_WARNINGS
#endif

#include <iostream>
#include <vector>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <boost/format.hpp>

#ifdef _WIN32
	#include <winsock2.h>
	#define poll WSAPoll
	#define close closesocket
	#pragma comment(lib, "ws2_32.lib")
#else
	#include <unistd.h>
	#include <sys/socket.h>
	#include <sys/poll.h>
	#include <netinet/in.h>
	#include <arpa/inet.h>
#endif

using namespace std;
using namespace boost;
typedef pair <char*, uint16_t> ClientInfo;
typedef map <int, ClientInfo> ClientMap;

const size_t BUFFER_SIZE = 1024;
const int POLL_TIMEOUT = 60 * 1000;
ClientMap online;

void die(const char* message);
string onCommand(const string& command, int client_fd);

int main(int argc, char *argv[]) {
	if (argc < 2) {
		cerr << "Error: port required" << endl;
		cout << format("Usage: %1% <port>") % argv[0] << endl;
		exit(EXIT_FAILURE);
	}

#ifdef _WIN32
	WSADATA wsa;
	if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
		cerr << format("Error initializing winsock: %1%") % WSAGetLastError() << endl;
		exit(EXIT_FAILURE);
	}
#endif

	int server_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (server_fd < 0) {
		die("Error opening socket");
	}

	struct sockaddr_in server_addr;
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = INADDR_ANY;
	server_addr.sin_port = htons(atoi(argv[1]));

	if (::bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
		die("Error binding address");
	}

	if (listen(server_fd, SOMAXCONN) < 0) {
		die("Error listening socket");
	}

	vector<struct pollfd> watch_fd(1);
	watch_fd[0].fd = server_fd;
	watch_fd[0].events = POLLIN;

	char* buffer = new char[BUFFER_SIZE];

	while (true) {
		cout << "Polling..." << endl;

		int active = poll(watch_fd.data(), watch_fd.size(), POLL_TIMEOUT);
		if (active <= 0) {
			if (active == 0) {
				cout << "poll() time out, no event happend" << endl;
				continue;
			} else {
				die("Error on poll()");
			}
		}

		// handle active client
		for (size_t i = 1; i < watch_fd.size(); i++) {
			if (watch_fd[i].revents == 0) {
				continue;
			} else {
				if (watch_fd[i].revents == POLLIN) {
					memset(buffer, 0, BUFFER_SIZE);
					int bytes = recv(watch_fd[i].fd, buffer, BUFFER_SIZE, 0);

					if (bytes > 0) {
						string response = onCommand(buffer, watch_fd[i].fd);

						if (send(watch_fd[i].fd, response.c_str(), response.length(), 0) > 0) {
							watch_fd[i].revents = 0;
							continue;
						} else {
							perror("Error on send()");
						}
					} else {
						if (bytes == 0) {
							cout << format("Client#%1% disconnected") % watch_fd[i].fd << endl;
						} else {
							perror("Error on recv()");
						}
					}
				} else {
					cerr << format("Unexpected event happend: %1%") % watch_fd[i].revents << endl;
				}

				close(watch_fd[i].fd);
				cout << format("Socket#%1% closed") % watch_fd[i].fd << endl;
				online.erase(watch_fd[i].fd);
				watch_fd.erase(watch_fd.begin() + i);
			}
		}

		// handle new client
		if (watch_fd[0].revents == POLLIN) {
			struct sockaddr_in client_addr;
			int client_addr_length = sizeof(client_addr);

			int client_fd = accept(server_fd, (struct sockaddr *) &client_addr, &client_addr_length);
			if (client_fd > 0) {
				char* ip = inet_ntoa(client_addr.sin_addr);
				uint16_t port = ntohs(client_addr.sin_port);

				cout << format("Client connected, ID: %1%, IP: %2%, Port: %3%") % client_fd % ip % port << endl;

				string hello = (format("Client ID: %1%\n") % client_fd).str();

				if (send(client_fd, hello.c_str(), hello.length(), 0) > 0) {
					struct pollfd poll_fd;
					poll_fd.fd = client_fd;
					poll_fd.events = POLLIN;

					watch_fd.push_back(poll_fd);
					online[client_fd] = ClientInfo(ip, port);
				} else {
					perror("Error on send()");
				}
			} else {
				perror("Error on accept()");
			}

			watch_fd[0].revents = 0;
		}
	}

	close(server_fd);

#ifdef _WIN32
	WSACleanup();
#endif

	return EXIT_SUCCESS;
}

void die(const char* message) {
	perror(message);
	exit(EXIT_FAILURE);
}

string onCommand(const string& command, int client_fd) {
	if (command.find('\n') == string::npos) {
		return "Bad request\n";
	}

	if (command == "time\n") {
		time_t now = time(NULL);
		return ctime(&now);
	}

	if (command == "name\n") {
		char hostname[128];
		gethostname(hostname, 128);
		return string(hostname) + '\n';
	}

	if (command == "list\n") {
		string response;
		for (auto client : online) {
			response += (format("ID: %1%,\tIP: %2%,\tPort: %3%\n") % client.first % client.second.first % client.second.second).str();
		}
		return response;
	}

	if (command.find("send") == 0) {
		try {
			size_t begin = command.find(' ');
			size_t end = command.find(' ', begin + 1);

			if (end == string::npos) {
				return "Invalid command\n";
			}

			int dest_fd = stoi(command.substr(begin, end));

			if (online.find(dest_fd) == online.end()) {
				return "No such client\n";
			} else {
				string message = (format("Client#%1%: %2%") % client_fd % command.substr(end + 1)).str();
				if (send(dest_fd, message.c_str(), message.length(), 0) > 0) {
					return "Send success\n";
				} else {
					return "Send failed\n";
				}
			}
		} catch (const invalid_argument&) {
			return "Invalid command\n";
		}
	}

	return "Invalid command\n";
}
<commit_msg>redefine POLLIN<commit_after>/*
* socket-server
*
* Simple socket server implementation based on poll()
* 2015 Yuzo(Huang Yuzhong)
*
* Server program arch:
* 		Master thread: Use poll() to handle multiple client.
*/

#ifdef _WIN32
	#define _CRT_SECURE_NO_WARNINGS
	#define _WINSOCK_DEPRECATED_NO_WARNINGS
#endif

#include <iostream>
#include <vector>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <boost/format.hpp>

#ifdef _WIN32
	#include <winsock2.h>
	#define poll WSAPoll
	#define close closesocket
	#define POLLIN POLLRDNORM
	#pragma comment(lib, "ws2_32.lib")
#else
	#include <unistd.h>
	#include <sys/socket.h>
	#include <sys/poll.h>
	#include <netinet/in.h>
	#include <arpa/inet.h>
#endif

using namespace std;
using namespace boost;
typedef pair <char*, uint16_t> ClientInfo;
typedef map <int, ClientInfo> ClientMap;

const size_t BUFFER_SIZE = 1024;
const int POLL_TIMEOUT = 60 * 1000;
ClientMap online;

void die(const char* message);
string onCommand(const string& command, int client_fd);

int main(int argc, char *argv[]) {
	if (argc < 2) {
		cerr << "Error: port required" << endl;
		cout << format("Usage: %1% <port>") % argv[0] << endl;
		exit(EXIT_FAILURE);
	}

#ifdef _WIN32
	WSADATA wsa;
	if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
		cerr << format("Error initializing winsock: %1%") % WSAGetLastError() << endl;
		exit(EXIT_FAILURE);
	}
#endif

	int server_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (server_fd < 0) {
		die("Error opening socket");
	}

	struct sockaddr_in server_addr;
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = INADDR_ANY;
	server_addr.sin_port = htons(atoi(argv[1]));

	if (::bind(server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
		die("Error binding address");
	}

	if (listen(server_fd, SOMAXCONN) < 0) {
		die("Error listening socket");
	}

	vector<struct pollfd> watch_fd(1);
	watch_fd[0].fd = server_fd;
	watch_fd[0].events = POLLIN;

	char* buffer = new char[BUFFER_SIZE];

	while (true) {
		cout << "Polling..." << endl;

		int active = poll(watch_fd.data(), watch_fd.size(), POLL_TIMEOUT);
		if (active <= 0) {
			if (active == 0) {
				cout << "poll() time out, no event happend" << endl;
				continue;
			} else {
				die("Error on poll()");
			}
		}

		// handle active client
		for (size_t i = 1; i < watch_fd.size(); i++) {
			if (watch_fd[i].revents == 0) {
				continue;
			} else {
				if (watch_fd[i].revents == POLLIN) {
					memset(buffer, 0, BUFFER_SIZE);
					int bytes = recv(watch_fd[i].fd, buffer, BUFFER_SIZE, 0);

					if (bytes > 0) {
						string response = onCommand(buffer, watch_fd[i].fd);

						if (send(watch_fd[i].fd, response.c_str(), response.length(), 0) > 0) {
							watch_fd[i].revents = 0;
							continue;
						} else {
							perror("Error on send()");
						}
					} else {
						if (bytes == 0) {
							cout << format("Client#%1% disconnected") % watch_fd[i].fd << endl;
						} else {
							perror("Error on recv()");
						}
					}
				} else {
					cerr << format("Unexpected event happend: %1%") % watch_fd[i].revents << endl;
				}

				close(watch_fd[i].fd);
				cout << format("Socket#%1% closed") % watch_fd[i].fd << endl;
				online.erase(watch_fd[i].fd);
				watch_fd.erase(watch_fd.begin() + i);
			}
		}

		// handle new client
		if (watch_fd[0].revents == POLLIN) {
			struct sockaddr_in client_addr;
			int client_addr_length = sizeof(client_addr);

			int client_fd = accept(server_fd, (struct sockaddr *) &client_addr, &client_addr_length);
			if (client_fd > 0) {
				char* ip = inet_ntoa(client_addr.sin_addr);
				uint16_t port = ntohs(client_addr.sin_port);

				cout << format("Client connected, ID: %1%, IP: %2%, Port: %3%") % client_fd % ip % port << endl;

				string hello = (format("Client ID: %1%\n") % client_fd).str();

				if (send(client_fd, hello.c_str(), hello.length(), 0) > 0) {
					struct pollfd poll_fd;
					poll_fd.fd = client_fd;
					poll_fd.events = POLLIN;

					watch_fd.push_back(poll_fd);
					online[client_fd] = ClientInfo(ip, port);
				} else {
					perror("Error on send()");
				}
			} else {
				perror("Error on accept()");
			}

			watch_fd[0].revents = 0;
		}
	}

	close(server_fd);

#ifdef _WIN32
	WSACleanup();
#endif

	return EXIT_SUCCESS;
}

void die(const char* message) {
	perror(message);
	exit(EXIT_FAILURE);
}

string onCommand(const string& command, int client_fd) {
	if (command.find('\n') == string::npos) {
		return "Bad request\n";
	}

	if (command == "time\n") {
		time_t now = time(NULL);
		return ctime(&now);
	}

	if (command == "name\n") {
		char hostname[128];
		gethostname(hostname, 128);
		return string(hostname) + '\n';
	}

	if (command == "list\n") {
		string response;
		for (auto client : online) {
			response += (format("ID: %1%,\tIP: %2%,\tPort: %3%\n") % client.first % client.second.first % client.second.second).str();
		}
		return response;
	}

	if (command.find("send") == 0) {
		try {
			size_t begin = command.find(' ');
			size_t end = command.find(' ', begin + 1);

			if (end == string::npos) {
				return "Invalid command\n";
			}

			int dest_fd = stoi(command.substr(begin, end));

			if (online.find(dest_fd) == online.end()) {
				return "No such client\n";
			} else {
				string message = (format("Client#%1%: %2%") % client_fd % command.substr(end + 1)).str();
				if (send(dest_fd, message.c_str(), message.length(), 0) > 0) {
					return "Send success\n";
				} else {
					return "Send failed\n";
				}
			}
		} catch (const invalid_argument&) {
			return "Invalid command\n";
		}
	}

	return "Invalid command\n";
}
<|endoftext|>