 Chromium Code Reviews
 Chromium Code Reviews Issue 99333019:
  Preserve modification timestamp when zipping files.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master
    
  
    Issue 99333019:
  Preserve modification timestamp when zipping files.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master| OLD | NEW | 
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include <set> | 5 #include <set> | 
| 6 #include <string> | |
| 6 #include <vector> | 7 #include <vector> | 
| 7 | 8 | 
| 8 #include "base/file_util.h" | 9 #include "base/file_util.h" | 
| 9 #include "base/files/file_enumerator.h" | 10 #include "base/files/file_enumerator.h" | 
| 10 #include "base/files/file_path.h" | 11 #include "base/files/file_path.h" | 
| 11 #include "base/files/scoped_temp_dir.h" | 12 #include "base/files/scoped_temp_dir.h" | 
| 12 #include "base/path_service.h" | 13 #include "base/path_service.h" | 
| 13 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" | 
| 14 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" | 
| 15 #include "testing/platform_test.h" | 16 #include "testing/platform_test.h" | 
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 91 size_t expected_count = 0; | 92 size_t expected_count = 0; | 
| 92 for (std::set<base::FilePath>::iterator iter = zip_contents_.begin(); | 93 for (std::set<base::FilePath>::iterator iter = zip_contents_.begin(); | 
| 93 iter != zip_contents_.end(); ++iter) { | 94 iter != zip_contents_.end(); ++iter) { | 
| 94 if (expect_hidden_files || iter->BaseName().value()[0] != '.') | 95 if (expect_hidden_files || iter->BaseName().value()[0] != '.') | 
| 95 ++expected_count; | 96 ++expected_count; | 
| 96 } | 97 } | 
| 97 | 98 | 
| 98 EXPECT_EQ(expected_count, count); | 99 EXPECT_EQ(expected_count, count); | 
| 99 } | 100 } | 
| 100 | 101 | 
| 102 void TestTimeStamp(const char* date_time, bool valid_year) { | |
| 
satorux1
2013/12/12 08:03:57
This function was a bit hard to follow.
Could you
 | |
| 103 SCOPED_TRACE(std::string("TestTimeStamp(") + date_time + ")"); | |
| 104 base::ScopedTempDir temp_dir; | |
| 105 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | |
| 106 | |
| 107 base::FilePath zip_file = temp_dir.path().AppendASCII("out.zip"); | |
| 108 base::FilePath src_dir = temp_dir.path().AppendASCII("input"); | |
| 109 base::FilePath out_dir = temp_dir.path().AppendASCII("output"); | |
| 110 | |
| 111 base::FilePath src_file = src_dir.AppendASCII("test.txt"); | |
| 112 base::FilePath out_file = out_dir.AppendASCII("test.txt"); | |
| 113 | |
| 114 EXPECT_TRUE(base::CreateDirectory(src_dir)); | |
| 115 EXPECT_TRUE(base::CreateDirectory(out_dir)); | |
| 116 | |
| 117 base::Time test_mtime; | |
| 118 ASSERT_TRUE(base::Time::FromString(date_time, &test_mtime)); | |
| 119 base::Time now_time = base::Time::Now() - base::TimeDelta::FromSeconds(1); | |
| 120 | |
| 121 EXPECT_EQ(1, file_util::WriteFile(src_file, "1", 1)); | |
| 122 EXPECT_TRUE(base::TouchFile(src_file, base::Time::Now(), test_mtime)); | |
| 123 | |
| 124 EXPECT_TRUE(zip::Zip(src_dir, zip_file, true)); | |
| 125 ASSERT_TRUE(zip::Unzip(zip_file, out_dir)); | |
| 126 | |
| 127 base::PlatformFileInfo file_info; | |
| 128 EXPECT_TRUE(base::GetFileInfo(out_file, &file_info)); | |
| 129 EXPECT_EQ(file_info.size, 1); | |
| 130 | |
| 131 if (valid_year) { | |
| 132 EXPECT_EQ(file_info.last_modified, test_mtime); | |
| 133 } else { | |
| 134 // Invalid date means the modification time will default to 'now'. | |
| 
satorux1
2013/12/12 08:03:57
now? I thought it's Unix Epoch. If so, please make
 | |
| 135 EXPECT_GE(file_info.last_modified, now_time); | |
| 136 } | |
| 137 } | |
| 138 | |
| 101 // The path to temporary directory used to contain the test operations. | 139 // The path to temporary directory used to contain the test operations. | 
| 102 base::FilePath test_dir_; | 140 base::FilePath test_dir_; | 
| 103 | 141 | 
| 104 base::ScopedTempDir temp_dir_; | 142 base::ScopedTempDir temp_dir_; | 
| 105 | 143 | 
| 106 // Hard-coded contents of a known zip file. | 144 // Hard-coded contents of a known zip file. | 
| 107 std::set<base::FilePath> zip_contents_; | 145 std::set<base::FilePath> zip_contents_; | 
| 108 | 146 | 
| 109 // Hard-coded list of relative paths for a zip file created with ZipFiles. | 147 // Hard-coded list of relative paths for a zip file created with ZipFiles. | 
| 110 std::vector<base::FilePath> zip_file_list_; | 148 std::vector<base::FilePath> zip_file_list_; | 
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 185 base::FilePath src_dir_russian = | 223 base::FilePath src_dir_russian = | 
| 186 temp_dir.path().Append(base::FilePath::FromUTF8Unsafe( | 224 temp_dir.path().Append(base::FilePath::FromUTF8Unsafe( | 
| 187 "\xD0\xA2\xD0\xB5\xD1\x81\xD1\x82")); | 225 "\xD0\xA2\xD0\xB5\xD1\x81\xD1\x82")); | 
| 188 base::CopyDirectory(src_dir, src_dir_russian, true); | 226 base::CopyDirectory(src_dir, src_dir_russian, true); | 
| 189 base::FilePath zip_file = temp_dir.path().AppendASCII("out_russian.zip"); | 227 base::FilePath zip_file = temp_dir.path().AppendASCII("out_russian.zip"); | 
| 190 | 228 | 
| 191 EXPECT_TRUE(zip::Zip(src_dir_russian, zip_file, true)); | 229 EXPECT_TRUE(zip::Zip(src_dir_russian, zip_file, true)); | 
| 192 TestUnzipFile(zip_file, true); | 230 TestUnzipFile(zip_file, true); | 
| 193 } | 231 } | 
| 194 | 232 | 
| 233 TEST_F(ZipTest, ZipTimeStamp) { | |
| 234 // The dates tested are arbitrary, with some constraints. The zip format can | |
| 235 // only store years from 1980 to 2107 and an even number of seconds, due to it | |
| 236 // using the ms dos date format. | |
| 237 | |
| 238 // Valid arbitrary date. | |
| 239 TestTimeStamp("23 Oct 1997 23:22:20", true); | |
| 240 | |
| 241 // Date before 1980, zip format limitation, must default to unix epoch. | |
| 242 TestTimeStamp("29 Dec 1979 21:00:10", false); | |
| 243 | |
| 244 // Despite the minizip headers telling the maximum year should be 2044, it | |
| 245 // can actually go up to 2107. Beyond that, the dos date format cannot store | |
| 246 // the year (2107-1980=127). To test that limit, the input file needs to be | |
| 247 // touched, but the code that modifies the file access and modification times | |
| 248 // relies on time_t which is defined as long, therefore being in many | |
| 249 // platforms just a 4-byte integer, like 32-bit Mac OSX or linux. As such, it | |
| 250 // suffers from the year-2038 bug. Therefore 2038 is the highest we can test | |
| 251 // in all platforms reliably. | |
| 252 TestTimeStamp("02 Jan 2038 23:59:58", true); | |
| 253 | |
| 254 // And here the year-2038 bug is avoided. | |
| 255 #if defined(OS_POSIX) | |
| 256 if (sizeof(time_t) == 8) | |
| 257 #elif defined(OS_WIN) | |
| 258 if (true) | |
| 259 #else | |
| 260 if (false) | |
| 
satorux1
2013/12/12 08:03:57
The #if-defs are complicated. I'd suggest remove t
 | |
| 261 #endif | |
| 262 TestTimeStamp("31 Oct 2107 23:59:58", true); | |
| 263 } | |
| 264 | |
| 195 #if defined(OS_POSIX) | 265 #if defined(OS_POSIX) | 
| 196 TEST_F(ZipTest, ZipFiles) { | 266 TEST_F(ZipTest, ZipFiles) { | 
| 197 base::FilePath src_dir; | 267 base::FilePath src_dir; | 
| 198 ASSERT_TRUE(GetTestDataDirectory(&src_dir)); | 268 ASSERT_TRUE(GetTestDataDirectory(&src_dir)); | 
| 199 src_dir = src_dir.AppendASCII("test"); | 269 src_dir = src_dir.AppendASCII("test"); | 
| 200 | 270 | 
| 201 base::ScopedTempDir temp_dir; | 271 base::ScopedTempDir temp_dir; | 
| 202 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 272 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 
| 203 base::FilePath zip_file = temp_dir.path().AppendASCII("out.zip"); | 273 base::FilePath zip_file = temp_dir.path().AppendASCII("out.zip"); | 
| 204 | 274 | 
| (...skipping 11 matching lines...) Expand all Loading... | |
| 216 EXPECT_TRUE(reader.LocateAndOpenEntry(zip_file_list_[i])); | 286 EXPECT_TRUE(reader.LocateAndOpenEntry(zip_file_list_[i])); | 
| 217 // Check the path in the entry just in case. | 287 // Check the path in the entry just in case. | 
| 218 const zip::ZipReader::EntryInfo* entry_info = reader.current_entry_info(); | 288 const zip::ZipReader::EntryInfo* entry_info = reader.current_entry_info(); | 
| 219 EXPECT_EQ(entry_info->file_path(), zip_file_list_[i]); | 289 EXPECT_EQ(entry_info->file_path(), zip_file_list_[i]); | 
| 220 } | 290 } | 
| 221 } | 291 } | 
| 222 #endif // defined(OS_POSIX) | 292 #endif // defined(OS_POSIX) | 
| 223 | 293 | 
| 224 } // namespace | 294 } // namespace | 
| 225 | 295 | 
| OLD | NEW |