| Index: extensions/common/permissions/permission_message_test_util.cc | 
| diff --git a/extensions/common/permissions/permission_message_test_util.cc b/extensions/common/permissions/permission_message_test_util.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..a9189cde54242c8c47c8f73becfd47126f6aecc4 | 
| --- /dev/null | 
| +++ b/extensions/common/permissions/permission_message_test_util.cc | 
| @@ -0,0 +1,368 @@ | 
| +// Copyright 2015 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 "extensions/common/permissions/permission_message_test_util.h" | 
| + | 
| +#include <algorithm> | 
| +#include <iterator> | 
| + | 
| +#include "base/strings/string_split.h" | 
| +#include "base/strings/string_util.h" | 
| +#include "base/strings/utf_string_conversions.h" | 
| +#include "extensions/common/permissions/permissions_data.h" | 
| + | 
| +// TODO(treib): Remove the legacy messages once we've fully switched to the new | 
| +// permission message system. | 
| + | 
| +namespace { | 
| + | 
| +using extensions::CoalescedPermissionMessage; | 
| +using extensions::CoalescedPermissionMessages; | 
| + | 
| +std::vector<base::string16> MakeVectorString16(const base::string16& str) { | 
| +  return std::vector<base::string16>(1, str); | 
| +} | 
| + | 
| +std::vector<base::string16> MakeVectorString16(const std::string& str) { | 
| +  return MakeVectorString16(base::UTF8ToUTF16(str)); | 
| +} | 
| + | 
| +std::vector<base::string16> MakeVectorString16(const base::string16& str1, | 
| +                                               const base::string16& str2) { | 
| +  std::vector<base::string16> result; | 
| +  result.push_back(str1); | 
| +  result.push_back(str2); | 
| +  return result; | 
| +} | 
| + | 
| +std::vector<base::string16> MakeVectorString16(const std::string& str1, | 
| +                                               const std::string& str2) { | 
| +  return MakeVectorString16(base::UTF8ToUTF16(str1), base::UTF8ToUTF16(str2)); | 
| +} | 
| + | 
| +std::vector<base::string16> MakeVectorString16( | 
| +    const std::vector<std::string>& vec) { | 
| +  std::vector<base::string16> result; | 
| +  for (const std::string& msg : vec) | 
| +    result.push_back(base::UTF8ToUTF16(msg)); | 
| +  return result; | 
| +} | 
| + | 
| +std::vector<std::vector<base::string16>> MakeVectorVectorString16( | 
| +    const std::vector<std::string>& vec) { | 
| +  return std::vector<std::vector<base::string16>>(1, MakeVectorString16(vec)); | 
| +} | 
| + | 
| +std::vector<std::vector<base::string16>> MakeVectorVectorString16( | 
| +    const std::vector<base::string16>& vec) { | 
| +  return std::vector<std::vector<base::string16>>(1, vec); | 
| +} | 
| + | 
| +std::vector<std::vector<base::string16>> MakeVectorVectorString16( | 
| +    const std::vector<std::vector<std::string>>& vecs) { | 
| +  std::vector<std::vector<base::string16>> result; | 
| +  for (const std::vector<std::string>& vec : vecs) | 
| +    result.push_back(MakeVectorString16(vec)); | 
| +  return result; | 
| +} | 
| + | 
| +// Returns the vector of messages concatenated into a single string, separated | 
| +// by newlines, e.g.: "Bar"\n"Baz"\n | 
| +base::string16 MessagesVectorToString( | 
| +    const std::vector<base::string16>& messages) { | 
| +  if (messages.empty()) | 
| +    return base::ASCIIToUTF16("\n"); | 
| +  return base::ASCIIToUTF16("\"") + | 
| +         JoinString(messages, base::ASCIIToUTF16("\"\n\"")) + | 
| +         base::ASCIIToUTF16("\"\n"); | 
| +} | 
| + | 
| +base::string16 MessagesToString(const CoalescedPermissionMessages& messages) { | 
| +  std::vector<base::string16> messages_vec; | 
| +  for (const CoalescedPermissionMessage& msg : messages) | 
| +    messages_vec.push_back(msg.message()); | 
| +  return MessagesVectorToString(messages_vec); | 
| +} | 
| + | 
| +std::vector<base::string16> SplitLegacyMessageDetails( | 
| +    const base::string16& legacy_message_details) { | 
| +  std::vector<base::string16> details; | 
| +  base::SplitString(legacy_message_details, base::char16('\n'), &details); | 
| +  return details; | 
| +} | 
| + | 
| +bool CheckThatSubmessagesMatch( | 
| +    const base::string16& message, | 
| +    const base::string16& actual_legacy_message_details, | 
| +    const std::vector<base::string16>& actual_submessages, | 
| +    const std::vector<base::string16>& expected_submessages) { | 
| +  bool result = true; | 
| + | 
| +  std::vector<base::string16> expected_sorted(expected_submessages); | 
| +  std::sort(expected_sorted.begin(), expected_sorted.end()); | 
| + | 
| +  std::vector<base::string16> actual_legacy_details = | 
| +      SplitLegacyMessageDetails(actual_legacy_message_details); | 
| +  std::sort(actual_legacy_details.begin(), actual_legacy_details.end()); | 
| +  if (expected_sorted != actual_legacy_details) { | 
| +    // This is always a failure, even within an EXPECT_FALSE. | 
| +    // Message: Expected details for "Message" to be { "Foo" }, but got | 
| +    // { "Bar", "Baz" } in the legacy system | 
| +    ADD_FAILURE() << "Expected details for \"" << message << "\" to be:\n" | 
| +                  << MessagesVectorToString(expected_sorted) << "But got:\n" | 
| +                  << MessagesVectorToString(actual_legacy_details) | 
| +                  << "in the legacy system"; | 
| +    result = false; | 
| +  } | 
| + | 
| +  std::vector<base::string16> actual_sorted(actual_submessages); | 
| +  std::sort(actual_sorted.begin(), actual_sorted.end()); | 
| +  if (actual_sorted != actual_submessages) { | 
| +    // This is always a failure, even within an EXPECT_FALSE. | 
| +    // Message: Expected submessages for "Message" to be { "Foo" }, but got | 
| +    // { "Bar", "Baz" } | 
| +    ADD_FAILURE() << "Expected submessages for \"" << message << "\" to be:\n" | 
| +                  << MessagesVectorToString(expected_sorted) << "But got:\n" | 
| +                  << MessagesVectorToString(actual_sorted); | 
| +    result = false; | 
| +  } | 
| + | 
| +  return result; | 
| +} | 
| + | 
| +testing::AssertionResult VerifyHasPermissionMessageImpl( | 
| +    const std::vector<base::string16>& actual_legacy_messages, | 
| +    const std::vector<base::string16>& actual_legacy_message_details, | 
| +    const CoalescedPermissionMessages& actual_messages, | 
| +    const base::string16& expected_message, | 
| +    const std::vector<base::string16>& expected_submessages) { | 
| +  CHECK_EQ(actual_legacy_messages.size(), actual_legacy_message_details.size()); | 
| + | 
| +  auto legacy_message_it = | 
| +      std::find(actual_legacy_messages.begin(), actual_legacy_messages.end(), | 
| +                expected_message); | 
| +  bool legacy_found = legacy_message_it != actual_legacy_messages.end(); | 
| + | 
| +  auto message_it = | 
| +      std::find_if(actual_messages.begin(), actual_messages.end(), | 
| +                   [&expected_message](const CoalescedPermissionMessage& msg) { | 
| +                     return msg.message() == expected_message; | 
| +                   }); | 
| +  bool found = message_it != actual_messages.end(); | 
| + | 
| +  if (legacy_found != found) { | 
| +    // This is always a failure, even within an EXPECT_FALSE. | 
| +    ADD_FAILURE() | 
| +        << "Mismatch between legacy and new system when looking for \"" | 
| +        << expected_message << "\".\nLegacy system returned:\n" | 
| +        << MessagesVectorToString(actual_legacy_messages) | 
| +        << "New system returned:\n" << MessagesToString(actual_messages); | 
| +    return testing::AssertionFailure(); | 
| +  } | 
| + | 
| +  if (!found) { | 
| +    // Message: Expected messages to contain "Foo", but got { "Bar", "Baz" } | 
| +    // in the legacy system | 
| +    return testing::AssertionFailure() << "Expected messages to contain \"" | 
| +                                       << expected_message << "\", but got " | 
| +                                       << MessagesToString(actual_messages); | 
| +  } | 
| + | 
| +  auto legacy_message_details_it = | 
| +      actual_legacy_message_details.begin() + | 
| +      std::distance(actual_legacy_messages.begin(), legacy_message_it); | 
| +  if (!CheckThatSubmessagesMatch(expected_message, *legacy_message_details_it, | 
| +                                 message_it->submessages(), | 
| +                                 expected_submessages)) { | 
| +    return testing::AssertionFailure(); | 
| +  } | 
| + | 
| +  // Message: Expected messages NOT to contain "Foo", but got { "Bar", "Baz" } | 
| +  return testing::AssertionSuccess() << "Expected messages NOT to contain \"" | 
| +                                     << expected_message << "\", but got " | 
| +                                     << MessagesToString(actual_messages); | 
| +} | 
| + | 
| +}  // namespace | 
| + | 
| +namespace extensions { | 
| + | 
| +testing::AssertionResult VerifyHasPermissionMessage( | 
| +    const PermissionsData* permissions_data, | 
| +    const std::string& expected_message) { | 
| +  return VerifyHasPermissionMessage(permissions_data, | 
| +                                    base::UTF8ToUTF16(expected_message)); | 
| +} | 
| + | 
| +testing::AssertionResult VerifyHasPermissionMessage( | 
| +    const PermissionsData* permissions_data, | 
| +    const base::string16& expected_message) { | 
| +  return VerifyHasPermissionMessageImpl( | 
| +      permissions_data->GetLegacyPermissionMessageStrings(), | 
| +      permissions_data->GetLegacyPermissionMessageDetailsStrings(), | 
| +      permissions_data->GetCoalescedPermissionMessages(), expected_message, | 
| +      std::vector<base::string16>()); | 
| +} | 
| + | 
| +testing::AssertionResult VerifyNoPermissionMessages( | 
| +    const PermissionsData* permissions_data) { | 
| +  return VerifyPermissionMessages(permissions_data, | 
| +                                  std::vector<base::string16>(), true); | 
| +} | 
| + | 
| +testing::AssertionResult VerifyOnePermissionMessage( | 
| +    const PermissionsData* permissions_data, | 
| +    const std::string& expected_message) { | 
| +  return VerifyPermissionMessages(permissions_data, | 
| +                                  MakeVectorString16(expected_message), true); | 
| +} | 
| + | 
| +testing::AssertionResult VerifyOnePermissionMessage( | 
| +    const PermissionsData* permissions_data, | 
| +    const base::string16& expected_message) { | 
| +  return VerifyPermissionMessages(permissions_data, | 
| +                                  MakeVectorString16(expected_message), true); | 
| +} | 
| + | 
| +testing::AssertionResult VerifyOnePermissionMessageWithSubmessages( | 
| +    const PermissionsData* permissions_data, | 
| +    const std::string& expected_message, | 
| +    const std::vector<std::string>& expected_submessages) { | 
| +  return VerifyPermissionMessagesWithSubmessages( | 
| +      permissions_data, MakeVectorString16(expected_message), | 
| +      MakeVectorVectorString16(expected_submessages), true); | 
| +} | 
| + | 
| +testing::AssertionResult VerifyOnePermissionMessageWithSubmessages( | 
| +    const PermissionsData* permissions_data, | 
| +    const base::string16& expected_message, | 
| +    const std::vector<base::string16>& expected_submessages) { | 
| +  return VerifyPermissionMessagesWithSubmessages( | 
| +      permissions_data, MakeVectorString16(expected_message), | 
| +      MakeVectorVectorString16(expected_submessages), true); | 
| +} | 
| + | 
| +testing::AssertionResult VerifyTwoPermissionMessages( | 
| +    const PermissionsData* permissions_data, | 
| +    const std::string& expected_message_1, | 
| +    const std::string& expected_message_2, | 
| +    bool check_order) { | 
| +  return VerifyPermissionMessages( | 
| +      permissions_data, | 
| +      MakeVectorString16(expected_message_1, expected_message_2), check_order); | 
| +} | 
| + | 
| +testing::AssertionResult VerifyTwoPermissionMessages( | 
| +    const PermissionsData* permissions_data, | 
| +    const base::string16& expected_message_1, | 
| +    const base::string16& expected_message_2, | 
| +    bool check_order) { | 
| +  return VerifyPermissionMessages( | 
| +      permissions_data, | 
| +      MakeVectorString16(expected_message_1, expected_message_2), check_order); | 
| +} | 
| + | 
| +testing::AssertionResult VerifyPermissionMessages( | 
| +    const PermissionsData* permissions_data, | 
| +    const std::vector<std::string>& expected_messages, | 
| +    bool check_order) { | 
| +  return VerifyPermissionMessages( | 
| +      permissions_data, MakeVectorString16(expected_messages), check_order); | 
| +} | 
| + | 
| +testing::AssertionResult VerifyPermissionMessages( | 
| +    const PermissionsData* permissions_data, | 
| +    const std::vector<base::string16>& expected_messages, | 
| +    bool check_order) { | 
| +  return VerifyPermissionMessagesWithSubmessages( | 
| +      permissions_data, expected_messages, | 
| +      std::vector<std::vector<base::string16>>(expected_messages.size()), | 
| +      check_order); | 
| +} | 
| + | 
| +testing::AssertionResult VerifyPermissionMessagesWithSubmessages( | 
| +    const PermissionsData* permissions_data, | 
| +    const std::vector<std::string>& expected_messages, | 
| +    const std::vector<std::vector<std::string>>& expected_submessages, | 
| +    bool check_order) { | 
| +  return VerifyPermissionMessagesWithSubmessages( | 
| +      permissions_data, MakeVectorString16(expected_messages), | 
| +      MakeVectorVectorString16(expected_submessages), check_order); | 
| +} | 
| + | 
| +testing::AssertionResult VerifyPermissionMessagesWithSubmessages( | 
| +    const PermissionsData* permissions_data, | 
| +    const std::vector<base::string16>& expected_messages, | 
| +    const std::vector<std::vector<base::string16>>& expected_submessages, | 
| +    bool check_order) { | 
| +  CHECK_EQ(expected_messages.size(), expected_submessages.size()); | 
| + | 
| +  std::vector<base::string16> actual_legacy_messages = | 
| +      permissions_data->GetLegacyPermissionMessageStrings(); | 
| +  std::vector<base::string16> actual_legacy_message_details = | 
| +      permissions_data->GetLegacyPermissionMessageDetailsStrings(); | 
| +  if (expected_messages.size() != actual_legacy_messages.size()) { | 
| +    // Message: Expected 2 messages { "Bar", "Baz" }, but got 0 {} in the | 
| +    // legacy system | 
| +    return testing::AssertionFailure() | 
| +           << "Expected " << expected_messages.size() << " messages:\n" | 
| +           << MessagesVectorToString(expected_messages) << "But got " | 
| +           << actual_legacy_messages.size() << " messages:\n" | 
| +           << MessagesVectorToString(actual_legacy_messages) | 
| +           << "in the legacy system"; | 
| +  } | 
| + | 
| +  CoalescedPermissionMessages actual_messages = | 
| +      permissions_data->GetCoalescedPermissionMessages(); | 
| +  if (expected_messages.size() != actual_messages.size()) { | 
| +    // Message: Expected 2 messages { "Bar", "Baz" }, but got 0 {} | 
| +    return testing::AssertionFailure() | 
| +           << "Expected " << expected_messages.size() << " messages:\n" | 
| +           << MessagesVectorToString(expected_messages) << "But got " | 
| +           << actual_messages.size() << " messages:\n" | 
| +           << MessagesToString(actual_messages); | 
| +  } | 
| + | 
| +  if (check_order) { | 
| +    auto msg_it = actual_messages.begin(); | 
| +    for (size_t i = 0; i < expected_messages.size(); i++, msg_it++) { | 
| +      const base::string16& expected_message = expected_messages[i]; | 
| + | 
| +      if (expected_message != actual_legacy_messages[i]) { | 
| +        // Message: Expected messages to be { "Foo" }, but got { "Bar", "Baz" } | 
| +        // in the legacy system | 
| +        return testing::AssertionFailure() | 
| +               << "Expected messages to be:\n" | 
| +               << MessagesVectorToString(expected_messages) << "But got:\n" | 
| +               << MessagesVectorToString(actual_legacy_messages) | 
| +               << "in the legacy system"; | 
| +      } | 
| + | 
| +      if (expected_message != msg_it->message()) { | 
| +        // Message: Expected messages to be { "Foo" }, but got { "Bar", "Baz" } | 
| +        return testing::AssertionFailure() | 
| +               << "Expected messages to be:\n" | 
| +               << MessagesVectorToString(expected_messages) << "But got:\n" | 
| +               << MessagesToString(actual_messages); | 
| +      } | 
| + | 
| +      if (!CheckThatSubmessagesMatch( | 
| +              expected_message, actual_legacy_message_details[i], | 
| +              msg_it->submessages(), expected_submessages[i])) { | 
| +        return testing::AssertionFailure(); | 
| +      } | 
| +    } | 
| +  } else { | 
| +    for (size_t i = 0; i < expected_messages.size(); i++) { | 
| +      testing::AssertionResult result = VerifyHasPermissionMessageImpl( | 
| +          actual_legacy_messages, actual_legacy_message_details, | 
| +          actual_messages, expected_messages[i], expected_submessages[i]); | 
| +      if (!result) | 
| +        return result; | 
| +    } | 
| +  } | 
| +  return testing::AssertionSuccess(); | 
| +} | 
| + | 
| +}  // namespace extensions | 
|  |