Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1375)

Unified Diff: chrome/browser/about_flags_unittest.cc

Issue 344883002: Collect UMA statistics on which chrome://flags lead to chrome restart on ChromeOS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update after review. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/about_flags_switches_histogram_ids.h ('k') | chrome/browser/chromeos/login/login_utils.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/about_flags_unittest.cc
diff --git a/chrome/browser/about_flags_unittest.cc b/chrome/browser/about_flags_unittest.cc
index 0cb9fa78835f36a552cf7fe0ffe1ed07170e7871..06e7595bd944045c61c1ceb5f8f899a7b1914685 100644
--- a/chrome/browser/about_flags_unittest.cc
+++ b/chrome/browser/about_flags_unittest.cc
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/files/file_path.h"
+#include "base/memory/scoped_vector.h"
+#include "base/path_service.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/testing_pref_service.h"
#include "base/strings/string_number_conversions.h"
@@ -13,6 +16,9 @@
#include "chrome/common/pref_names.h"
#include "grit/chromium_strings.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/libxml/chromium/libxml_utils.h"
+
+namespace {
const char kFlags1[] = "flag1";
const char kFlags2[] = "flag2";
@@ -32,14 +38,163 @@ const char kValueForMultiSwitch2[] = "value_for_multi_switch2";
const char kEnableDisableValue1[] = "value1";
const char kEnableDisableValue2[] = "value2";
+std::map<int, std::string> ParseEnumFromHistogramsXml(
+ const std::string& enum_name,
+ XmlReader& reader);
Ilya Sherman 2014/07/31 00:37:51 Please define the function here, rather than forwa
Alexander Alekseev 2014/07/31 01:32:06 Done.
+
+// Find and read given enum (with integer values) from histograms.xml.
+// |enum_name| - enum name.
+// |histograms_xml| - must be loaded histograms.xml file.
+//
+// Returns map { value => label } so that:
+// <int value="9" label="enable-pinch-virtual-viewport"/>
+// becomes:
+// { 9 => "enable-pinch-virtual-viewport" }
+// Returns empty map on error.
+std::map<int, std::string> ReadEnumFromHistogramsXml(
+ const std::string& enum_name,
+ XmlReader& histograms_xml) {
Ilya Sherman 2014/07/31 00:37:51 nit: Variables should be passed either by const-re
Alexander Alekseev 2014/07/31 01:32:06 Done.
+ std::map<int, std::string> login_custom_flags;
+
+ // Implement simple DFS.
Ilya Sherman 2014/07/31 00:37:51 nit: "DFS" -> "depth first search"
Alexander Alekseev 2014/07/31 01:32:06 Done.
+ while (true) {
+ const std::string node_name = histograms_xml.NodeName();
+ if (node_name == "enum") {
+ std::string name;
+ if (histograms_xml.NodeAttribute("name", &name) && name == enum_name) {
+ if (!login_custom_flags.empty()) {
+ EXPECT_TRUE(login_custom_flags.empty())
+ << "Duplicate enum '" << enum_name << "' found in histograms.xml";
+ return std::map<int, std::string>();
+ }
+
+ const bool got_into_enum = histograms_xml.Read();
+ if (got_into_enum) {
+ login_custom_flags =
+ ParseEnumFromHistogramsXml(enum_name, histograms_xml);
+ EXPECT_FALSE(login_custom_flags.empty())
+ << "Bad enum '" << enum_name
+ << "' found in histograms.xml (format error).";
+ } else {
+ EXPECT_TRUE(got_into_enum)
+ << "Bad enum '" << enum_name
+ << "' (looks empty) found in histograms.xml.";
+ }
+ if (login_custom_flags.empty())
+ return std::map<int, std::string>();
+ }
+ }
+ // Go deeper if possible (stops at the closing tag of the deepest node).
+ if (histograms_xml.Read())
+ continue;
+
+ // Try next node on the same level (skips closing tag).
+ if (histograms_xml.Next())
+ continue;
+
+ // Go up until next node on the same level exists.
+ while (histograms_xml.Depth() && !histograms_xml.SkipToElement()) {
+ }
+
+ // Reached top. histograms.xml consists of the single top level node
+ // 'histogram-configuration', so this is the end.
+ if (!histograms_xml.Depth())
+ break;
+ }
+ EXPECT_FALSE(login_custom_flags.empty())
+ << "Enum '" << enum_name << "' is not found in histograms.xml.";
+ return login_custom_flags;
+}
+
+// This is a helper function to the previous one.
+// Extracts single enum (with integer values) from histograms.xml.
+// Expects |reader| to point at given enum.
+// Returns map { value => label }.
+// Returns empty map on error.
+std::map<int, std::string> ParseEnumFromHistogramsXml(
+ const std::string& enum_name,
+ XmlReader& reader) {
Ilya Sherman 2014/07/31 00:37:51 Ditto.
Alexander Alekseev 2014/07/31 01:32:06 Done.
+ int entries_index = -1;
+
+ std::map<int, std::string> result;
+ bool success = true;
+
+ while (true) {
+ const std::string node_name = reader.NodeName();
+ if (node_name == "enum" && reader.IsClosingElement())
+ break;
+
+ if (node_name == "int") {
+ ++entries_index;
+ std::string value_str;
+ std::string label;
+ const bool has_value = reader.NodeAttribute("value", &value_str);
+ const bool has_label = reader.NodeAttribute("label", &label);
+ if (!has_value) {
+ ADD_FAILURE() << "Bad " << enum_name << " enum entry (at index "
+ << entries_index << ", label='" << label
+ << "'): No 'value' attribute.";
+ success = false;
+ }
+ if (!has_label) {
+ ADD_FAILURE() << "Bad " << enum_name << " enum entry (at index "
+ << entries_index << ", value_str='" << value_str
+ << "'): No 'label' attribute.";
+ success = false;
+ }
+
+ int value;
+ if (has_value && !base::StringToInt(value_str, &value)) {
+ ADD_FAILURE() << "Bad " << enum_name << " enum entry (at index "
+ << entries_index << ", label='" << label
+ << "', value_str='" << value_str
+ << "'): 'value' attribute is not integer.";
+ success = false;
+ }
+ if (success) {
+ result[value] = label;
+ }
+ }
+ // All enum entries are on the same level, so it is enough to iterate
+ // until possible.
+ reader.Next();
+ }
+ return (success ? result : std::map<int, std::string>());
+}
+
+std::string FilePathStringTypeToString(const base::FilePath::StringType& path) {
+#if defined(OS_WIN)
+ return UTF16ToUTF8(path);
+#else
+ return path;
+#endif
+}
+
+} // anonymous namespace
+
namespace about_flags {
+enum TestSwitchesHistogramIDs {
+ ID_UNKNOWN_FLAG = UMA_HISTOGRAM_ID_UNKNOWN_FLAG,
+ ID_BAD_FLAG_FORMAT = UMA_HISTOGRAM_ID_BAD_FLAG_FORMAT,
+ ID_kMultiSwitch1,
+ ID_kMultiSwitch2,
+ ID_kSwitch1,
+ ID_kSwitch2,
+ ID_kSwitch3,
+};
+
+#define ID(x) static_cast<const about_flags::SwitchesUmaHistogramId>(x)
+
const Experiment::Choice kMultiChoices[] = {
- { IDS_PRODUCT_NAME, "", "" },
- { IDS_PRODUCT_NAME, kMultiSwitch1, "" },
- { IDS_PRODUCT_NAME, kMultiSwitch2, kValueForMultiSwitch2 },
+ { IDS_PRODUCT_NAME, "", "", ID(ID_UNKNOWN_FLAG) },
+ { IDS_PRODUCT_NAME, kMultiSwitch1, "", ID(ID_kMultiSwitch1) },
+ { IDS_PRODUCT_NAME,
+ kMultiSwitch2, kValueForMultiSwitch2, ID(ID_kMultiSwitch2) },
};
+#undef ID
+
// The experiments that are set for these tests. The 3rd experiment is not
// supported on the current platform, all others are.
static Experiment kExperiments[] = {
@@ -51,8 +206,10 @@ static Experiment kExperiments[] = {
Experiment::SINGLE_VALUE,
kSwitch1,
"",
+ ID_kSwitch1,
NULL,
NULL,
+ 0,
NULL,
0
},
@@ -64,8 +221,10 @@ static Experiment kExperiments[] = {
Experiment::SINGLE_VALUE,
kSwitch2,
kValueForSwitch2,
+ ID_kSwitch2,
NULL,
NULL,
+ 0,
NULL,
0
},
@@ -77,8 +236,10 @@ static Experiment kExperiments[] = {
Experiment::SINGLE_VALUE,
kSwitch3,
"",
+ ID_kSwitch3,
NULL,
NULL,
+ 0,
NULL,
0
},
@@ -90,8 +251,10 @@ static Experiment kExperiments[] = {
Experiment::MULTI_VALUE,
"",
"",
+ 0,
"",
"",
+ 0,
kMultiChoices,
arraysize(kMultiChoices)
},
@@ -103,18 +266,271 @@ static Experiment kExperiments[] = {
Experiment::ENABLE_DISABLE_VALUE,
kSwitch1,
kEnableDisableValue1,
+ ID_kSwitch1,
kSwitch2,
kEnableDisableValue2,
+ ID_kSwitch2,
NULL,
3
},
};
+/*
+ This table contains histogram IDs for switches. Switch ID must never change!
+*/
+const char* const HistogramSwitchesOrdered[] = {
+ NULL, /* No flag */
+ NULL, /* Bad flag format */
+ NULL, /* reserved */
+ NULL, /* reserved */
+ NULL, /* reserved */
+ "disable-webrtc-hw-encoding",
+ "disable-minimize-on-second-launcher-item-click",
+ "disable-virtual-keyboard-overscroll",
+ "disable-virtual-keyboard-overscroll",
+ "enable-pinch-virtual-viewport",
+ "prefetch-search-results",
+ "enable-experimental-app-list",
+ "enable-devtools-experiments",
+ "enable-centered-app-list",
+ "enable-accelerated-overflow-scroll",
+ "enable-tcp-fastopen",
+ "enable-zero-suggest-personalized",
+ "enable-experimental-web-platform-features",
+ "use-simple-cache-backend",
+ "disable-search-button-in-omnibox",
+ "file-manager-enable-new-audio-player",
+ "disable-prefixed-encrypted-media",
+ "disable-origin-chip",
+ "disable-touch-adjustment",
+ "disable-offline-auto-reload",
+ "enable-fixed-position-compositing",
+ "enable-nacl",
+ "disable-saml-signin",
+ "disable-views-rect-based-targeting",
+ "enable-linkable-ephemeral-apps",
+ "enable-zero-copy",
+ "enable-session-crashed-bubble",
+ "enable-spelling-auto-correct",
+ "disable-suggestions-service",
+ "disable-app-list-app-info",
+ "allow-insecure-websocket-from-https-origin",
+ "enable-input-view",
+ "enable-web-midi",
+ "disable-app-list-voice-search",
+ "disable-offline-load-stale-cache",
+ "manual-enhanced-bookmarks",
+ "num-raster-threads",
+ "disable-cast",
+ "enable-instant-search-clicks",
+ "enable-zero-suggest-ether-noserp",
+ "enable-overlay-scrollbar",
+ "enable-spdy4",
+ "disable-boot-animation",
+ "disable-password-generation",
+ "disable-software-rasterizer",
+ "enable-avfoundation",
+ "disable-spdy-proxy-dev-auth-origin",
+ "disable-new-profile-management",
+ "mediadrm-enable-non-compositing",
+ "disable-text-input-focus-manager",
+ "enable-smooth-scrolling",
+ "enable-password-generation",
+ "disable-device-discovery",
+ "scroll-end-effect",
+ "enable-delegated-renderer",
+ "ash-enable-touch-view-testing",
+ "touch-events",
+ "disable-new-ntp",
+ "disable-permissions-bubbles",
+ "enable-network-portal-notification",
+ "disable-media-source",
+ "enable-encrypted-media",
+ "enable-apps-file-associations",
+ "enable-search-button-in-omnibox-for-str",
+ "disable-sync-app-list",
+ "file-manager-enable-new-gallery",
+ "enable-fast-unload",
+ "disable-fast-text-autosizing",
+ "tab-capture-upscale-quality",
+ "disable-threaded-compositing",
+ "enable-accelerated-fixed-root-background",
+ "enable-lcd-text",
+ "nacl-debug-mask",
+ "disable-transition-compositing",
+ "enable-embeddedsearch-api",
+ "enable-settings-window",
+ "force-device-scale-factor",
+ "disable-password-manager-reauthentication",
+ "disable-pinch-virtual-viewport",
+ "disable-webgl",
+ "save-page-as-mhtml",
+ "disable-zero-suggest",
+ "show-composited-layer-borders",
+ "enable-zero-suggest-most-visited",
+ "enable-answers-in-suggest",
+ "malware-interstitial-v3",
+ "enable-virtual-keyboard",
+ "disable-quic",
+ "default-tile-width",
+ "enable-automatic-password-saving",
+ "enable-search-button-in-omnibox-always",
+ "disable-input-view",
+ "enable-one-copy",
+ "overscroll-history-navigation",
+ "enable-quic-https",
+ "js-flags",
+ "enable-nacl-debug",
+ "enable-viewport-meta",
+ "enable-experimental-input-view-features",
+ "disable-gpu-rasterization",
+ "enable-print-preview-register-promos",
+ "enable-simplified-fullscreen",
+ "enable-accessibility-tab-switcher",
+ "enable-quic",
+ "enable-origin-chip-on-srp",
+ "fast-user-switching",
+ "enable-touch-editing",
+ "wallet-service-use-sandbox",
+ "enable-carrier-switching",
+ "disable-contextual-search",
+ "enable-zero-suggest-ether-serp",
+ "enable-cloud-devices",
+ "disable-quic-https",
+ "enable-touch-drag-drop",
+ "enable-permissions-bubbles",
+ "enable-first-run-ui-transitions",
+ "disable-device-discovery-notifications",
+ "enable-threaded-compositing",
+ "enable-easy-unlock",
+ "enable-origin-chip-always",
+ "enable-pinch",
+ "enable-bleeding-edge-rendering-fast-paths",
+ "disable-lcd-text",
+ "enable-streamlined-hosted-apps",
+ "disable-webrtc",
+ "enable-save-password-bubble",
+ "enable-apps-show-on-first-paint",
+ "enable-new-ntp",
+ "enable-text-input-focus-manager",
+ "enable-service-worker-sync",
+ "enable-harfbuzz-rendertext",
+ "enable-download-resumption",
+ "new-profile-management",
+ "disable-touch-editing",
+ "google-profile-info",
+ "enable-impl-side-painting",
+ "enable-distance-field-text",
+ "enable-deferred-image-decoding",
+ "manual-enhanced-bookmarks-optout",
+ "enable-search-button-in-omnibox-for-str-or-iip",
+ "enable-offline-auto-reload",
+ "enable-experimental-canvas-features",
+ "enable-app-install-alerts",
+ "enable-cloud-print-xps",
+ "max-tiles-for-interest-area",
+ "enable-app-list",
+ "disable-accelerated-video-decode",
+ "out-of-process-pdf",
+ "disable-session-crashed-bubble",
+ "enable-swipe-selection",
+ "disable-fixed-position-compositing",
+ "enable-web-based-signin",
+ "ssl-interstitial-v2-gray",
+ "enable-sync-app-list",
+ "disable-compositor-touch-hit-testing",
+ "disable-accelerated-fixed-root-background",
+ "enhanced-bookmarks-experiment",
+ "disable-pnacl",
+ "extension-content-verification",
+ "disable-touch-drag-drop",
+ "default-tile-height",
+ "disable-sync-synced-notifications",
+ "new-avatar-menu",
+ "allow-nacl-socket-api",
+ "enable-experimental-extension-apis",
+ "enable-app-window-controls",
+ "silent-debugger-extension-api",
+ "enable-suggestions-service",
+ "enable-contextual-search",
+ "enable-fast-text-autosizing",
+ "ash-touch-hud",
+ "disable-accelerated-overflow-scroll",
+ "disable-async-dns",
+ "disable-webaudio",
+ "disable-delegated-renderer",
+ "disable-save-password-bubble",
+ "enable-offline-load-stale-cache",
+ "disable-display-color-calibration",
+ "debug-packed-apps",
+ "enable-gpu-rasterization",
+ "disable-impl-side-painting",
+ "disable-distance-field-text",
+ "performance-monitor-gathering",
+ "disable-pinch",
+ "enable-syncfs-directory-operation",
+ "disable-ntp-other-sessions-menu",
+ "enable-spelling-feedback-field-trial",
+ "ssl-interstitial-v1",
+ "disable-gesture-requirement-for-media-playback",
+ "touch-scrolling-mode",
+ "enable-touchpad-three-finger-click",
+ "disable-quickoffice-component-app",
+ "enable-transition-compositing",
+ "disable-account-consistency",
+ "enable-request-tablet-site",
+ "tab-capture-downscale-quality",
+ "enable-service-worker",
+ "ash-debug-shortcuts",
+ "enable-sync-synced-notifications",
+ "ignore-gpu-blacklist",
+ "ssl-interstitial-v2-colorful",
+ "do-not-ignore-autocomplete-off",
+ "disable-accelerated-2d-canvas",
+ "enable-gesture-tap-highlight",
+ "reset-app-list-install-state",
+ "enable-scroll-prediction",
+ "enable-ephemeral-apps",
+ "enable-webgl-draft-extensions",
+ "disable-network-portal-notification",
+ "enable-device-discovery-notifications",
+ "disable-layer-squashing",
+ "disable-gesture-tap-highlight",
+ "enable-offline-auto-reload-visible-only",
+ "enable-spdy-proxy-dev-auth-origin",
+ "enable-translate-new-ux",
+ "no-pings",
+ "enable-scripts-require-action",
+ "disable-webrtc-hw-decoding",
+ "enable-virtual-keyboard-overscroll",
+ "disable-direct-write",
+ "extensions-on-chrome-urls",
+ "malware-interstitial-v2",
+ "enable-account-consistency",
+ "disable-offline-auto-reload-visible-only",
+ "disable-settings-window",
+ "disable-embedded-shared-worker",
+ "show-autofill-type-predictions",
+ "enable-async-dns",
+ "enable-prominent-url-app-flow",
+ "enable-high-dpi-fixed-position-compositing",
+ "force-gpu-rasterization",
+ "disable-device-enumeration",
+ "show-fps-counter",
+ "apps-keep-chrome-alive",
+ "enable-filemanager-mtp",
+ "enable-panels",
+ "disable-overlay-scrollbar",
+ "disable-zero-copy",
+ "disable-click-delay",
+};
+
class AboutFlagsTest : public ::testing::Test {
protected:
AboutFlagsTest() : flags_storage_(&prefs_) {
prefs_.registry()->RegisterListPref(prefs::kEnabledLabsExperiments);
testing::ClearState();
+ InitHistogramIdToSwitch();
}
virtual void SetUp() OVERRIDE {
@@ -133,11 +549,37 @@ class AboutFlagsTest : public ::testing::Test {
testing::SetExperiments(NULL, 0);
}
+ private:
+ void InitHistogramIdToSwitch() {
+ // Extract command-line switches from kExperiments to
+ // histogram_id_to_switch_ in the order of UMA IDs. Each switch is stored
+ // by the idex equal to its ID.
+ const SwitchesHistogramIDs& switch_histogram_id = GetSwitchesHistogramIds();
+ for (SwitchesHistogramIDs::const_iterator it = switch_histogram_id.begin();
+ it != switch_histogram_id.end();
+ ++it) {
+ const int id = it->second;
+ if (static_cast<int>(histogram_id_to_switch_.size()) > id) {
+ // Check that enum values are not reused in kExperiments[], i.e.
+ // different switches have different UMA IDs values.
+ // (There is another check for equal switches below.)
+ EXPECT_FALSE(histogram_id_to_switch_[id])
+ << "Duplicate switch histogram ID: " << id << ": '"
+ << *(histogram_id_to_switch_[id]) << "' conflicts with '"
+ << it->first << "'.";
+ } else {
+ histogram_id_to_switch_.resize(id + 1);
+ }
+ histogram_id_to_switch_[id] = new std::string(it->first);
+ }
+ }
+
+ protected:
TestingPrefServiceSimple prefs_;
PrefServiceFlagsStorage flags_storage_;
+ ScopedVector<std::string> histogram_id_to_switch_;
};
-
TEST_F(AboutFlagsTest, NoChangeNoRestart) {
EXPECT_FALSE(IsRestartNeededToCommitChanges());
SetExperimentEnabled(&flags_storage_, kFlags1, false);
@@ -233,22 +675,45 @@ TEST_F(AboutFlagsTest, ConvertFlagsToSwitches) {
EXPECT_FALSE(command_line2.HasSwitch(switches::kFlagSwitchesEnd));
}
+CommandLine::StringType CreateSwitch(const std::string& value) {
+#if defined(OS_WIN)
+ return ASCIIToUTF16(value);
+#else
+ return value;
+#endif
+}
+
TEST_F(AboutFlagsTest, CompareSwitchesToCurrentCommandLine) {
SetExperimentEnabled(&flags_storage_, kFlags1, true);
+ const std::string kDoubleDash("--");
+
CommandLine command_line(CommandLine::NO_PROGRAM);
command_line.AppendSwitch("foo");
CommandLine new_command_line(CommandLine::NO_PROGRAM);
ConvertFlagsToSwitches(&flags_storage_, &new_command_line, kAddSentinels);
- EXPECT_FALSE(AreSwitchesIdenticalToCurrentCommandLine(new_command_line,
- command_line));
+ EXPECT_FALSE(AreSwitchesIdenticalToCurrentCommandLine(
+ new_command_line, command_line, NULL));
+ {
+ std::set<CommandLine::StringType> difference;
+ EXPECT_FALSE(AreSwitchesIdenticalToCurrentCommandLine(
+ new_command_line, command_line, &difference));
+ EXPECT_EQ(1U, difference.size());
+ EXPECT_EQ(1U, difference.count(CreateSwitch(kDoubleDash + kSwitch1)));
+ }
ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels);
- EXPECT_TRUE(AreSwitchesIdenticalToCurrentCommandLine(new_command_line,
- command_line));
+ EXPECT_TRUE(AreSwitchesIdenticalToCurrentCommandLine(
+ new_command_line, command_line, NULL));
+ {
+ std::set<CommandLine::StringType> difference;
+ EXPECT_TRUE(AreSwitchesIdenticalToCurrentCommandLine(
+ new_command_line, command_line, &difference));
+ EXPECT_TRUE(difference.empty());
+ }
// Now both have flags but different.
SetExperimentEnabled(&flags_storage_, kFlags1, false);
@@ -257,8 +722,18 @@ TEST_F(AboutFlagsTest, CompareSwitchesToCurrentCommandLine) {
CommandLine another_command_line(CommandLine::NO_PROGRAM);
ConvertFlagsToSwitches(&flags_storage_, &another_command_line, kAddSentinels);
- EXPECT_FALSE(AreSwitchesIdenticalToCurrentCommandLine(new_command_line,
- another_command_line));
+ EXPECT_FALSE(AreSwitchesIdenticalToCurrentCommandLine(
+ new_command_line, another_command_line, NULL));
+ {
+ std::set<CommandLine::StringType> difference;
+ EXPECT_FALSE(AreSwitchesIdenticalToCurrentCommandLine(
+ new_command_line, another_command_line, &difference));
+ EXPECT_EQ(2U, difference.size());
+ EXPECT_EQ(1U, difference.count(CreateSwitch(kDoubleDash + kSwitch1)));
+ EXPECT_EQ(1U,
+ difference.count(CreateSwitch(kDoubleDash + kSwitch2 + "=" +
+ kValueForSwitch2)));
+ }
}
TEST_F(AboutFlagsTest, RemoveFlagSwitches) {
@@ -464,4 +939,91 @@ TEST_F(AboutFlagsTest, NoSeparators) {
}
}
+// Checks that enum values are not reused in kExperiments[], i.e. equal
+// switches have equal UMA IDs. (Different switches are checked in
+// AboutFlagsTest::AboutFlagsTest().)
+TEST_F(AboutFlagsTest, SwitchHistogramTableValid) {
+ if (histogram_id_to_switch_[0])
+ EXPECT_EQ(std::string(), histogram_id_to_switch_[0]->c_str());
+ ASSERT_GT(histogram_id_to_switch_.size(), 5U);
+ EXPECT_FALSE(histogram_id_to_switch_[1]); /* BAD_FLAG_FORMAT, */
+ EXPECT_FALSE(histogram_id_to_switch_[2]); /* RESERVED1 */
+ EXPECT_FALSE(histogram_id_to_switch_[3]); /* RESERVED2 */
+ EXPECT_FALSE(histogram_id_to_switch_[4]); /* RESERVED3 */
+ for (size_t i = 5; i < histogram_id_to_switch_.size(); ++i) {
+ // Some values may be missing from histogram_id_to_switch_[] because
+ // they are under #ifdef and were not compiled.
+ if (histogram_id_to_switch_[i]) {
+ EXPECT_LT(i, arraysize(HistogramSwitchesOrdered))
+ << "Switch index " << i << " (switch name '"
+ << histogram_id_to_switch_[i]->c_str()
+ << "') is found in about_flags, but missing from the test.";
+ } else {
+ EXPECT_LT(i, arraysize(HistogramSwitchesOrdered))
+ << "Switch index " << i
+ << " is found in about_flags, but missing from the test.";
+ }
+ if (i >= arraysize(HistogramSwitchesOrdered))
+ continue;
+
+ if (histogram_id_to_switch_[i]) {
+ EXPECT_STREQ(HistogramSwitchesOrdered[i],
+ histogram_id_to_switch_[i]->c_str())
+ << "Switch index " << i << " is wrong.";
+ }
+ }
+}
+
+TEST_F(AboutFlagsTest, CheckHistograms) {
+ base::FilePath histograms_xml_file_path;
+ ASSERT_TRUE(
+ PathService::Get(base::DIR_SOURCE_ROOT, &histograms_xml_file_path));
+ histograms_xml_file_path = histograms_xml_file_path.AppendASCII("tools")
+ .AppendASCII("metrics")
+ .AppendASCII("histograms")
+ .AppendASCII("histograms.xml");
+
+ XmlReader histograms_xml;
+ ASSERT_TRUE(histograms_xml.LoadFile(
+ FilePathStringTypeToString(histograms_xml_file_path.value())));
+ // Check that order and labels of <enum name="LoginCustomFlags" type="int">
+ // match HistogramSwitchesOrdered.
+ std::map<int, std::string> login_custom_flags =
+ ReadEnumFromHistogramsXml("LoginCustomFlags", histograms_xml);
+ ASSERT_TRUE(login_custom_flags.size())
+ << "Error reading enum 'LoginCustomFlags' from histograms.xml.";
+
+ for (size_t i = 5; i < arraysize(HistogramSwitchesOrdered); ++i) {
+ EXPECT_TRUE(login_custom_flags.count(i))
+ << "histograms.xml enum LoginCustomFlags doesn't contain switch '"
+ << HistogramSwitchesOrdered[i] << "'";
+
+ if (login_custom_flags.count(i)) {
+ EXPECT_STREQ(HistogramSwitchesOrdered[i], login_custom_flags[i].c_str())
+ << "Bad histograms.xml enum LoginCustomFlags entry with value='" << i
+ << "'.";
+ }
+ }
+
+ // If maximum index in histograms.xml is greater than in test,
+ // report all extra items.
+ if (static_cast<size_t>(login_custom_flags.rbegin()->first) >=
+ arraysize(HistogramSwitchesOrdered)) {
+ for (std::map<int, std::string>::reverse_iterator iter =
+ login_custom_flags.rbegin();
+ iter != login_custom_flags.rend();
+ ++iter) {
+ if (static_cast<size_t>(iter->first) <
+ arraysize(HistogramSwitchesOrdered)) {
+ break;
+ }
+ EXPECT_LT(static_cast<size_t>(iter->first),
+ arraysize(HistogramSwitchesOrdered))
+ << "Test has no data for histograms.xml enum LoginCustomFlags entry "
+ "with value='" << iter->first << "' label='" << iter->second
+ << "'";
+ }
+ }
+}
+
} // namespace about_flags
« no previous file with comments | « chrome/browser/about_flags_switches_histogram_ids.h ('k') | chrome/browser/chromeos/login/login_utils.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698