Commit bfdd3068 authored by Filip Filmar's avatar Filip Filmar Committed by Commit Bot

[i18n] Adds the setup for tzdata loading

The tzdata is loaded only for OS_FUCHSIA, since Fuchsia is the only OS
that needs this.  Fuchsia needs tzdata loading because it supports
multiple runners, and it is important that all of them use exactly the
same tzdata version.

If the tzdata files are not present, the execution proceeds, but the
files are not loaded.

In production, the runner will get time zone data from the config data
directory which is made available to apps in specific Fuchsia products.

Two unit tests are added:
1. A unit test that confirms tzdata loading affects the reported library
  revision.

  This test confirms that the loading mechanism works.

2. A unit test that checks whether the loaded timezone data revision
  matches what Fuchsia expects to see.

  This test will fail if loading fails so that the version in use is
  different from what Fuchsia expects.  This allows Fuchsia engs to
  see how to fix the harmful version skew.  This falilure should happen
  only if ICU libraries in Fuchsia and Chromium become backward-incompatible,
  which is unlikely but possible.


R=dpranke@chromium.org, wez@chromium.org

Bug: fuchsia:37487
Change-Id: I884777befbdb0ea9e324acc6c4359145c54d02aa
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1949120
Commit-Queue: Filip Filmar <fmil@google.com>
Reviewed-by: default avatarWez <wez@chromium.org>
Cr-Commit-Position: refs/heads/master@{#731684}
parent bcaa2760
...@@ -3040,6 +3040,7 @@ test("base_unittests") { ...@@ -3040,6 +3040,7 @@ test("base_unittests") {
"fuchsia/service_directory_test_base.cc", "fuchsia/service_directory_test_base.cc",
"fuchsia/service_directory_test_base.h", "fuchsia/service_directory_test_base.h",
"fuchsia/service_provider_impl_unittest.cc", "fuchsia/service_provider_impl_unittest.cc",
"fuchsia/time_zone_data_unittest.cc",
"message_loop/fd_watch_controller_posix_unittest.cc", "message_loop/fd_watch_controller_posix_unittest.cc",
"posix/file_descriptor_shuffle_unittest.cc", "posix/file_descriptor_shuffle_unittest.cc",
"task/thread_pool/task_tracker_posix_unittest.cc", "task/thread_pool/task_tracker_posix_unittest.cc",
......
...@@ -167,14 +167,6 @@ class IntlProfileWatcherTest : public testing::Test { ...@@ -167,14 +167,6 @@ class IntlProfileWatcherTest : public testing::Test {
base::RunLoop run_loop_; base::RunLoop run_loop_;
}; };
// Unit tests are run in an environment where intl is not provided, so the FIDL
// calls always fail.
TEST(IntlServiceNotAvailableTest, GetPrimaryTimeZoneIdForIcuInitialization) {
EXPECT_STREQ(
"",
IntlProfileWatcher::GetPrimaryTimeZoneIdForIcuInitialization().c_str());
}
// Unit tests are run in an environment where intl is not provided. // Unit tests are run in an environment where intl is not provided.
// However, this is not exposed by the API. // However, this is not exposed by the API.
TEST(IntlServiceNotAvailableTest, IntlProfileWatcher) { TEST(IntlServiceNotAvailableTest, IntlProfileWatcher) {
......
// Copyright (c) 2019 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/i18n/icu_util.h"
#include "base/environment.h"
#include "base/files/file_util.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/icu/source/common/unicode/uclean.h"
#include "third_party/icu/source/i18n/unicode/timezone.h"
namespace base {
namespace i18n {
class TimeZoneDataTest : public testing::Test {
protected:
TimeZoneDataTest() : env_(base::Environment::Create()) {}
void TearDown() override { u_cleanup(); }
void GetActualRevision(std::string* icu_version) {
UErrorCode err = U_ZERO_ERROR;
*icu_version = icu::TimeZone::getTZDataVersion(err);
ASSERT_EQ(U_ZERO_ERROR, err) << u_errorName(err);
}
std::unique_ptr<base::Environment> env_;
};
TEST_F(TimeZoneDataTest, RevisionFromConfig) {
// Config data is not available on Chromium test runners, so don't actually
// run this test there. A marker for this is the presence of revision.txt.
if (!base::PathExists(base::FilePath("/config/data/tzdata/revision.txt")))
return;
// Ensure that timezone data is loaded from the default location.
ASSERT_TRUE(env_->UnSetVar("ICU_TIMEZONE_FILES_DIR"));
InitializeICU();
std::string expected;
ASSERT_TRUE(base::ReadFileToString(
base::FilePath("/config/data/tzdata/revision.txt"), &expected));
std::string actual;
GetActualRevision(&actual);
EXPECT_EQ(expected, actual);
}
TEST_F(TimeZoneDataTest, RevisionFromTestData) {
// Ensure that timezone data is loaded from test data.
ASSERT_TRUE(env_->SetVar("ICU_TIMEZONE_FILES_DIR",
"/pkg/base/test/data/tzdata/2019a/44/le"));
InitializeICU();
std::string actual;
GetActualRevision(&actual);
EXPECT_EQ("2019a", actual);
}
} // namespace i18n
} // namespace base
...@@ -11,7 +11,9 @@ ...@@ -11,7 +11,9 @@
#include <string> #include <string>
#include "base/debug/alias.h" #include "base/debug/alias.h"
#include "base/environment.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/memory_mapped_file.h" #include "base/files/memory_mapped_file.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/path_service.h" #include "base/path_service.h"
...@@ -79,6 +81,28 @@ wchar_t g_debug_icu_pf_filename[_MAX_PATH]; ...@@ -79,6 +81,28 @@ wchar_t g_debug_icu_pf_filename[_MAX_PATH];
const char kIcuDataFileName[] = "icudtl.dat"; const char kIcuDataFileName[] = "icudtl.dat";
const char kIcuExtraDataFileName[] = "icudtl_extra.dat"; const char kIcuExtraDataFileName[] = "icudtl_extra.dat";
// Time zone data loading.
// For now, only Fuchsia has a meaningful use case for this feature, so it is
// only implemented for OS_FUCHSIA.
#if defined(OS_FUCHSIA)
// The environment variable used to point the ICU data loader to the directory
// containing timezone data. This is available from ICU version 54. The env
// variable approach is antiquated by today's standards (2019), but is the
// recommended way to configure ICU.
//
// See for details: http://userguide.icu-project.org/datetime/timezone
const char kIcuTimeZoneEnvVariable[] = "ICU_TIMEZONE_FILES_DIR";
// We assume that Fuchsia will provide time zone data at this path for Chromium
// to load, and that the path will be timely updated when Fuchsia needs to
// uprev the ICU version it is using. There are unit tests that will fail at
// Fuchsia roll time in case either Chromium or Fuchsia get upgraded to
// mutually incompatible ICU versions. That should be enough to alert the
// developers of the need to keep ICU library versions in ICU and Fuchsia in
// reasonable sync.
const char kIcuTimeZoneDataDir[] = "/config/data/tzdata/icu/44/le";
#endif // defined(OS_FUCHSIA)
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
const char kAssetsPathPrefix[] = "assets/"; const char kAssetsPathPrefix[] = "assets/";
#endif // defined(OS_ANDROID) #endif // defined(OS_ANDROID)
...@@ -181,10 +205,38 @@ void LazyOpenIcuDataFile() { ...@@ -181,10 +205,38 @@ void LazyOpenIcuDataFile() {
g_icudtl_region = pf_region->region; g_icudtl_region = pf_region->region;
} }
// Loads timezone data, for configurations where it makes sense. If the
// timezone data directory is not set up properly, we continue, but log
// appropriate information for debugging.
void InitializeTimeZoneData() {
#if defined(OS_FUCHSIA)
std::unique_ptr<base::Environment> env = base::Environment::Create();
// We only set the variable if it was not already set by a test. Fuchsia
// normally does not otherwise set env variables in production code.
if (!env->HasVar(kIcuTimeZoneEnvVariable)) {
env->SetVar(kIcuTimeZoneEnvVariable, kIcuTimeZoneDataDir);
}
std::string tzdata_dir;
env->GetVar(kIcuTimeZoneEnvVariable, &tzdata_dir);
// Try opening the path to check if present. No need to verify that it is a
// directory since ICU loading will return an error if the TimeZone data is
// wrong.
if (!base::DirectoryExists(base::FilePath(tzdata_dir))) {
PLOG(ERROR) << "Could not open: '" << tzdata_dir
<< "', proceeding without loading the timezone database";
return;
}
#endif // defined(OS_FUCHSIA)
}
int LoadIcuData(PlatformFile data_fd, int LoadIcuData(PlatformFile data_fd,
const MemoryMappedFile::Region& data_region, const MemoryMappedFile::Region& data_region,
std::unique_ptr<MemoryMappedFile>* out_mapped_data_file, std::unique_ptr<MemoryMappedFile>* out_mapped_data_file,
UErrorCode* out_error_code) { UErrorCode* out_error_code) {
InitializeTimeZoneData();
if (data_fd == kInvalidPlatformFile) { if (data_fd == kInvalidPlatformFile) {
LOG(ERROR) << "Invalid file descriptor to ICU data received."; LOG(ERROR) << "Invalid file descriptor to ICU data received.";
return 1; // To debug http://crbug.com/445616. return 1; // To debug http://crbug.com/445616.
......
# Timezone data for testing
This directory contains the fixed timezone data version 2019a for testing. It
is used in the runner tests to show that loading these files from a specified
location results in the TZ data version "2019a" becoming available to the
binaries.
{ {
"sandbox": { "sandbox": {
"features": [ "features": [
"config-data",
"isolated-persistent-storage", "isolated-persistent-storage",
"isolated-temp", "isolated-temp",
"root-ssl-certificates", "root-ssl-certificates",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment