chromium/chrome/browser/nearby_sharing/contacts/nearby_share_contacts_sorter_unittest.cc

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/nearby_sharing/contacts/nearby_share_contacts_sorter.h"

#include <algorithm>
#include <random>
#include <string>
#include <vector>

#include "base/no_destructor.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/nearby/sharing/proto/rpc_resources.pb.h"

namespace {

const std::vector<nearby::sharing::proto::ContactRecord>& contacts() {
  static const base::NoDestructor<
      std::vector<nearby::sharing::proto::ContactRecord>>
      contacts([] {
        nearby::sharing::proto::ContactRecord contact0;
        contact0.set_person_name("Claire");
        contact0.set_is_reachable(true);

        nearby::sharing::proto::ContactRecord contact1;
        contact1.set_person_name("Alice");
        contact1.add_identifiers()->set_account_name("[email protected]");
        contact1.set_is_reachable(true);

        nearby::sharing::proto::ContactRecord contact2;
        contact2.set_person_name("Alice");
        contact2.add_identifiers()->set_account_name("[email protected]");
        contact2.set_is_reachable(true);

        nearby::sharing::proto::ContactRecord contact3;
        contact3.add_identifiers()->set_account_name("[email protected]");
        contact3.set_is_reachable(true);

        nearby::sharing::proto::ContactRecord contact4;
        contact4.add_identifiers()->set_phone_number("222-222-2222");
        contact4.set_is_reachable(true);

        nearby::sharing::proto::ContactRecord contact5;
        contact5.add_identifiers()->set_phone_number("111-111-1111");
        contact5.set_is_reachable(true);

        nearby::sharing::proto::ContactRecord contact6;
        contact6.set_person_name("David");
        contact6.add_identifiers()->set_account_name("[email protected]");
        contact6.add_identifiers()->set_phone_number("222-222-2222");
        contact6.set_is_reachable(true);

        nearby::sharing::proto::ContactRecord contact7;
        contact7.set_person_name("David");
        contact7.add_identifiers()->set_account_name("[email protected]");
        contact7.add_identifiers()->set_phone_number("111-111-1111");
        contact7.set_id("2");
        contact7.set_is_reachable(true);

        nearby::sharing::proto::ContactRecord contact8;
        contact8.set_person_name("David");
        contact8.add_identifiers()->set_account_name("[email protected]");
        contact8.add_identifiers()->set_phone_number("111-111-1111");
        contact8.set_id("1");
        contact8.set_is_reachable(true);

        nearby::sharing::proto::ContactRecord contact9;
        contact9.set_person_name("中村光");
        contact9.set_is_reachable(true);

        nearby::sharing::proto::ContactRecord contact10;
        contact10.set_person_name("王皓");
        contact10.set_is_reachable(true);

        nearby::sharing::proto::ContactRecord contact11;
        contact11.set_person_name("中村俊輔");
        contact11.set_is_reachable(true);

        nearby::sharing::proto::ContactRecord contact12;
        contact12.set_person_name("丁立人");
        contact12.set_is_reachable(true);

        nearby::sharing::proto::ContactRecord contact13;
        contact13.set_person_name("Á");
        contact13.set_is_reachable(true);

        nearby::sharing::proto::ContactRecord contact14;
        contact14.set_person_name("Ñ");
        contact14.set_is_reachable(true);

        nearby::sharing::proto::ContactRecord contact15;
        contact15.set_person_name("å");
        contact15.set_id("5");
        contact15.set_is_reachable(true);

        nearby::sharing::proto::ContactRecord contact16;
        contact16.set_person_name("Å");
        contact16.set_id("3");
        contact16.set_is_reachable(true);

        nearby::sharing::proto::ContactRecord contact17;
        contact17.set_person_name("åz");
        contact17.set_id("4");
        contact17.set_is_reachable(true);

        nearby::sharing::proto::ContactRecord contact18;
        contact18.set_person_name("Opus");
        contact18.set_is_reachable(true);

        return std::vector<nearby::sharing::proto::ContactRecord>{
            contact0,  contact1,  contact2,  contact3,  contact4,
            contact5,  contact6,  contact7,  contact8,  contact9,
            contact10, contact11, contact12, contact13, contact14,
            contact15, contact16, contact17, contact18};
      }());
  return *contacts;
}

void VerifySort(
    const std::vector<nearby::sharing::proto::ContactRecord>& expected_contacts,
    const std::vector<nearby::sharing::proto::ContactRecord>& unsorted_contacts,
    icu::Locale locale) {
  // Try a few different permutations of |unsorted_contacts|, which should all
  // be sorted to |expected_contacts|.
  auto rng = std::default_random_engine{};
  for (size_t i = 0; i < 10u; ++i) {
    std::vector<nearby::sharing::proto::ContactRecord> sorted_contacts =
        contacts();
    std::shuffle(sorted_contacts.begin(), sorted_contacts.end(), rng);
    SortNearbyShareContactRecords(&sorted_contacts, locale);

    ASSERT_EQ(expected_contacts.size(), sorted_contacts.size());
    for (size_t j = 0; j < expected_contacts.size(); ++j) {
      EXPECT_EQ(expected_contacts[j].SerializeAsString(),
                sorted_contacts[j].SerializeAsString());
    }
  }
}

}  // namespace

TEST(NearbyShareContactsSorter, US) {
  // Expected ordering:
  //  Á        |               |              |
  //  å        |               |              | ID: 5
  //  Å        |               |              | ID: 3
  //  Alice    | [email protected]   |              |
  //  Alice    | [email protected]   |              |
  //  åz       |               |              | ID: 4
  //           | [email protected] |              |
  //  Claire   |               |              |
  //  David    | [email protected]   | 111-111-1111 | ID: 1
  //  David    | [email protected]   | 111-111-1111 | ID: 2
  //  David    | [email protected]   | 222-222-2222 |
  //  Ñ        |               |              |
  //  Opus     |               |              |
  //  丁立人   |               |              |
  //  中村俊輔 |               |              |
  //  中村光   |               |              |
  //  王皓     |               |              |
  //           |               | 111-111-1111 |
  //           |               | 222-222-2222 |
  std::vector<nearby::sharing::proto::ContactRecord> expected_contacts{
      contacts()[13], contacts()[15], contacts()[16], contacts()[2],
      contacts()[1],  contacts()[17], contacts()[3],  contacts()[0],
      contacts()[8],  contacts()[7],  contacts()[6],  contacts()[14],
      contacts()[18], contacts()[12], contacts()[11], contacts()[9],
      contacts()[10], contacts()[5],  contacts()[4]};
  VerifySort(expected_contacts, contacts(), icu::Locale::getUS());
}

TEST(NearbyShareContactsSorter, Sweden) {
  // Expected ordering:
  //  Á        |               |              |
  //  Alice    | [email protected]   |              |
  //  Alice    | [email protected]   |              |
  //           | [email protected] |              |
  //  Claire   |               |              |
  //  David    | [email protected]   | 111-111-1111 | ID: 1
  //  David    | [email protected]   | 111-111-1111 | ID: 2
  //  David    | [email protected]   | 222-222-2222 |
  //  Ñ        |               |              |
  //  Opus     |               |              |
  //  å        |               |              | ID: 5
  //  Å        |               |              | ID: 3
  //  åz       |               |              | ID: 4
  //  丁立人   |               |              |
  //  中村俊輔 |               |              |
  //  中村光   |               |              |
  //  王皓     |               |              |
  //           |               | 111-111-1111 |
  //           |               | 222-222-2222 |
  std::vector<nearby::sharing::proto::ContactRecord> expected_contacts{
      contacts()[13], contacts()[2],  contacts()[1],  contacts()[3],
      contacts()[0],  contacts()[8],  contacts()[7],  contacts()[6],
      contacts()[14], contacts()[18], contacts()[15], contacts()[16],
      contacts()[17], contacts()[12], contacts()[11], contacts()[9],
      contacts()[10], contacts()[5],  contacts()[4]};
  VerifySort(expected_contacts, contacts(),
             icu::Locale("SV", "SV", "Traditional_POSIX"));
}

TEST(NearbyShareContactsSorter, China) {
  // Expected ordering:
  //  丁立人   |               |              |
  //  王皓     |               |              |
  //  中村光   |               |              |
  //  中村俊輔 |               |              |
  //  Á        |               |              |
  //  å        |               |              | ID: 5
  //  Å        |               |              | ID: 3
  //  Alice    | [email protected]   |              |
  //  Alice    | [email protected]   |              |
  //  åz       |               |              | ID: 4
  //           | [email protected] |              |
  //  Claire   |               |              |
  //  David    | [email protected]   | 111-111-1111 | ID: 1
  //  David    | [email protected]   | 111-111-1111 | ID: 2
  //  David    | [email protected]   | 222-222-2222 |
  //  Ñ        |               |              |
  //  Opus     |               |              |
  //           |               | 111-111-1111 |
  //           |               | 222-222-2222 |
  std::vector<nearby::sharing::proto::ContactRecord> expected_contacts{
      contacts()[12], contacts()[10], contacts()[9],  contacts()[11],
      contacts()[13], contacts()[15], contacts()[16], contacts()[2],
      contacts()[1],  contacts()[17], contacts()[3],  contacts()[0],
      contacts()[8],  contacts()[7],  contacts()[6],  contacts()[14],
      contacts()[18], contacts()[5],  contacts()[4]};
  VerifySort(expected_contacts, contacts(), icu::Locale::getChina());
}