chromium/ui/base/resource/data_pack_with_resource_sharing_lacros_unittest.cc

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

#include "ui/base/resource/data_pack_with_resource_sharing_lacros.h"

#include <filesystem>
#include <map>
#include <string>
#include <string_view>
#include <utility>

#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/path_service.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/resource/data_pack.h"
#include "ui/base/resource/resource_scale_factor.h"

namespace ui {

class DataPackWithResourceSharingTest
    : public testing::TestWithParam<DataPack::TextEncodingType> {
 public:
  DataPackWithResourceSharingTest() {}
};

INSTANTIATE_TEST_SUITE_P(LoadFromPathWithAshResourceBINARY,
                         DataPackWithResourceSharingTest,
                         ::testing::Values(DataPack::BINARY));
INSTANTIATE_TEST_SUITE_P(LoadFromPathWithAshResourceUTF8,
                         DataPackWithResourceSharingTest,
                         ::testing::Values(DataPack::UTF8));
INSTANTIATE_TEST_SUITE_P(LoadFromPathWithAshResourceUTF16,
                         DataPackWithResourceSharingTest,
                         ::testing::Values(DataPack::UTF16));

TEST_P(DataPackWithResourceSharingTest, LoadFromPathWithAshResource) {
  base::ScopedTempDir dir;
  ASSERT_TRUE(dir.CreateUniqueTempDir());
  base::FilePath lacros_file =
      dir.GetPath().Append(FILE_PATH_LITERAL("lacros_data.pak"));
  base::FilePath ash_file =
      dir.GetPath().Append(FILE_PATH_LITERAL("ash_data.pak"));
  base::FilePath shared_resource_file =
      dir.GetPath().Append(FILE_PATH_LITERAL("shared_resource_data.pak"));

  std::string one("one");
  std::string two("two");
  std::string three("three");
  std::string zero("zero");

  std::map<uint16_t, std::string_view> lacros_resources;
  lacros_resources.emplace(1, std::string_view(one));
  lacros_resources.emplace(2, std::string_view(two));
  lacros_resources.emplace(3, std::string_view(three));
  ASSERT_TRUE(DataPack::WritePack(lacros_file, lacros_resources, GetParam()));

  std::map<uint16_t, std::string_view> ash_resources;
  ash_resources.emplace(1, std::string_view(one));
  ash_resources.emplace(2, std::string_view(zero));
  ash_resources.emplace(4, std::string_view(three));
  ASSERT_TRUE(DataPack::WritePack(ash_file, ash_resources, GetParam()));

  ASSERT_TRUE(DataPackWithResourceSharing::MaybeGenerateFallbackAndMapping(
      ash_file, lacros_file, shared_resource_file, k100Percent));

  DataPackWithResourceSharing pack(k100Percent);
  ASSERT_TRUE(pack.LoadFromPathWithAshResource(shared_resource_file, ash_file));

  ASSERT_EQ(pack.GetStringPiece(1), std::optional<std::string_view>(one));
  ASSERT_EQ(pack.GetStringPiece(2), std::optional<std::string_view>(two));
  ASSERT_EQ(pack.GetStringPiece(3), std::optional<std::string_view>(three));

  EXPECT_EQ(2U, pack.GetMappingTableSizeForTesting());
  EXPECT_EQ(pack.GetMappingByMappingTableIndexForTesting(0)->lacros_resource_id,
            1);
  EXPECT_EQ(pack.GetMappingByMappingTableIndexForTesting(0)->ash_resource_id,
            1);
  EXPECT_EQ(pack.GetMappingByMappingTableIndexForTesting(1)->lacros_resource_id,
            3);
  EXPECT_EQ(pack.GetMappingByMappingTableIndexForTesting(1)->ash_resource_id,
            4);
}

TEST_P(DataPackWithResourceSharingTest, LoadFromPathWithAshResourceWithAlias) {
  base::ScopedTempDir dir;
  ASSERT_TRUE(dir.CreateUniqueTempDir());
  base::FilePath lacros_file =
      dir.GetPath().Append(FILE_PATH_LITERAL("lacros_data.pak"));
  base::FilePath ash_file =
      dir.GetPath().Append(FILE_PATH_LITERAL("ash_data.pak"));
  base::FilePath shared_resource_file =
      dir.GetPath().Append(FILE_PATH_LITERAL("shared_resource_data.pak"));

  std::string one("one");
  std::string two("two");
  std::string three("three");
  std::string zero("zero");

  std::map<uint16_t, std::string_view> lacros_resources;
  lacros_resources.emplace(1, std::string_view(one));
  lacros_resources.emplace(2, std::string_view(two));
  lacros_resources.emplace(3, std::string_view(three));
  // Add resources registered as Alias.
  lacros_resources.emplace(11, std::string_view(one));
  lacros_resources.emplace(12, std::string_view(two));
  lacros_resources.emplace(13, std::string_view(three));
  ASSERT_TRUE(DataPack::WritePack(lacros_file, lacros_resources, GetParam()));

  std::map<uint16_t, std::string_view> ash_resources;
  ash_resources.emplace(1, std::string_view(one));
  ash_resources.emplace(2, std::string_view(zero));
  ash_resources.emplace(4, std::string_view(three));
  ASSERT_TRUE(DataPack::WritePack(ash_file, ash_resources, GetParam()));

  ASSERT_TRUE(DataPackWithResourceSharing::MaybeGenerateFallbackAndMapping(
      ash_file, lacros_file, shared_resource_file, k100Percent));

  DataPackWithResourceSharing pack(k100Percent);
  ASSERT_TRUE(pack.LoadFromPathWithAshResource(shared_resource_file, ash_file));

  ASSERT_EQ(pack.GetStringPiece(1), std::optional<std::string_view>(one));
  ASSERT_EQ(pack.GetStringPiece(2), std::optional<std::string_view>(two));
  ASSERT_EQ(pack.GetStringPiece(3), std::optional<std::string_view>(three));
  ASSERT_EQ(pack.GetStringPiece(11), std::optional<std::string_view>(one));
  ASSERT_EQ(pack.GetStringPiece(12), std::optional<std::string_view>(two));
  ASSERT_EQ(pack.GetStringPiece(13), std::optional<std::string_view>(three));

  EXPECT_EQ(4U, pack.GetMappingTableSizeForTesting());
  EXPECT_EQ(pack.GetMappingByMappingTableIndexForTesting(0)->lacros_resource_id,
            1);
  EXPECT_EQ(pack.GetMappingByMappingTableIndexForTesting(0)->ash_resource_id,
            1);
  EXPECT_EQ(pack.GetMappingByMappingTableIndexForTesting(1)->lacros_resource_id,
            3);
  EXPECT_EQ(pack.GetMappingByMappingTableIndexForTesting(1)->ash_resource_id,
            4);
  EXPECT_EQ(pack.GetMappingByMappingTableIndexForTesting(2)->lacros_resource_id,
            11);
  EXPECT_EQ(pack.GetMappingByMappingTableIndexForTesting(2)->ash_resource_id,
            1);
  EXPECT_EQ(pack.GetMappingByMappingTableIndexForTesting(3)->lacros_resource_id,
            13);
  EXPECT_EQ(pack.GetMappingByMappingTableIndexForTesting(3)->ash_resource_id,
            4);
}

TEST_P(DataPackWithResourceSharingTest, LoadMappingTableWithAshIDNotExisting) {
  base::ScopedTempDir dir;
  ASSERT_TRUE(dir.CreateUniqueTempDir());
  base::FilePath ash_file =
      dir.GetPath().Append(FILE_PATH_LITERAL("ash_data.pak"));
  base::FilePath shared_resource_file =
      dir.GetPath().Append(FILE_PATH_LITERAL("shared_resource_data.pak"));

  std::string one("one");
  std::string zero("zero");

  std::map<uint16_t, std::string_view> ash_resources;
  ash_resources.emplace(1, std::string_view(one));
  ash_resources.emplace(2, std::string_view(zero));
  ASSERT_TRUE(DataPack::WritePack(ash_file, ash_resources, GetParam()));

  using Mapping = DataPackWithResourceSharing::Mapping;
  std::vector<Mapping> mapping_table;
  mapping_table.push_back(Mapping(1, 1));
  mapping_table.push_back(Mapping(2, 3));

  DataPackWithResourceSharing::WriteSharedResourceFileForTesting(
      shared_resource_file, std::move(mapping_table));

  // If mapping_table points to Ash ID which doesn't exist, load should fail.
  DataPackWithResourceSharing pack(k100Percent);
  ASSERT_FALSE(
      pack.LoadFromPathWithAshResource(shared_resource_file, ash_file));
}

TEST_P(DataPackWithResourceSharingTest,
       LoadMappingTableWithDuplicatedLacrosID) {
  base::ScopedTempDir dir;
  ASSERT_TRUE(dir.CreateUniqueTempDir());
  base::FilePath ash_file =
      dir.GetPath().Append(FILE_PATH_LITERAL("ash_data.pak"));
  base::FilePath shared_resource_file =
      dir.GetPath().Append(FILE_PATH_LITERAL("shared_resource_data.pak"));

  std::string one("one");
  std::string zero("zero");

  std::map<uint16_t, std::string_view> ash_resources;
  ash_resources.emplace(1, std::string_view(one));
  ash_resources.emplace(2, std::string_view(zero));
  ASSERT_TRUE(DataPack::WritePack(ash_file, ash_resources, GetParam()));

  using Mapping = DataPackWithResourceSharing::Mapping;
  std::vector<Mapping> mapping_table;
  mapping_table.push_back(Mapping(1, 1));
  mapping_table.push_back(Mapping(1, 2));

  DataPackWithResourceSharing::WriteSharedResourceFileForTesting(
      shared_resource_file, std::move(mapping_table));

  // If a lacros resource id is mapped to more than 1 ash resource id, it should
  // fail.
  DataPackWithResourceSharing pack(k100Percent);
  ASSERT_FALSE(
      pack.LoadFromPathWithAshResource(shared_resource_file, ash_file));
}

TEST_P(DataPackWithResourceSharingTest, OnFailedToGenerateFile) {
  base::ScopedTempDir dir;
  ASSERT_TRUE(dir.CreateUniqueTempDir());
  base::FilePath empty_ash_file =
      dir.GetPath().Append(FILE_PATH_LITERAL("ash_data.pak"));
  base::FilePath lacros_file =
      dir.GetPath().Append(FILE_PATH_LITERAL("lacros_data.pak"));
  base::FilePath shared_resource_file =
      dir.GetPath().Append(FILE_PATH_LITERAL("shared_resource_data.pak"));

  std::string one("one");
  std::string two("two");

  std::map<uint16_t, std::string_view> lacros_resources;
  lacros_resources.emplace(1, std::string_view(one));
  lacros_resources.emplace(2, std::string_view(two));
  ASSERT_TRUE(DataPack::WritePack(lacros_file, lacros_resources, GetParam()));

  ASSERT_FALSE(DataPackWithResourceSharing::MaybeGenerateFallbackAndMapping(
      empty_ash_file, lacros_file, shared_resource_file, k100Percent));

  DataPackWithResourceSharing pack(k100Percent);
  ASSERT_FALSE(
      pack.LoadFromPathWithAshResource(shared_resource_file, empty_ash_file));

  EXPECT_FALSE(base::PathExists(shared_resource_file));
}

}  // namespace ui