1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
23345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Use of this source code is governed by a BSD-style license that can be
33345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// found in the LICENSE file.
43345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
53345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/file_util.h"
6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_temp_dir.h"
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/platform_file.h"
83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/time.h"
93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "testing/gtest/include/gtest/gtest.h"
103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricknamespace {
123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Reads from a file the given number of bytes, or until EOF is reached.
143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Returns the number of bytes read.
153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint ReadFully(base::PlatformFile file, int64 offset, char* data, int size) {
163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int total_bytes_read = 0;
173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int bytes_read;
183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  while (total_bytes_read < size) {
193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    bytes_read = base::ReadPlatformFile(
203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        file, offset + total_bytes_read, &data[total_bytes_read],
213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        size - total_bytes_read);
223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // If we reached EOF, bytes_read will be 0.
243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (bytes_read == 0)
253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return total_bytes_read;
263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if ((bytes_read < 0) || (bytes_read > size - total_bytes_read))
283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return -1;
293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    total_bytes_read += bytes_read;
313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return total_bytes_read;
343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Writes the given number of bytes to a file.
373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Returns the number of bytes written.
383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint WriteFully(base::PlatformFile file, int64 offset,
393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick               const char* data, int size) {
403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int total_bytes_written = 0;
413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int bytes_written;
423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  while (total_bytes_written < size) {
433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    bytes_written = base::WritePlatformFile(
443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        file, offset + total_bytes_written, &data[total_bytes_written],
453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        size - total_bytes_written);
463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if ((bytes_written == 0) && (size == 0))
483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return 0;
493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if ((bytes_written <= 0) || (bytes_written > size - total_bytes_written))
513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return -1;
523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    total_bytes_written += bytes_written;
543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return total_bytes_written;
573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} // namespace
603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
613345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST(PlatformFile, CreatePlatformFile) {
623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ScopedTempDir temp_dir;
633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  FilePath file_path = temp_dir.path().AppendASCII("create_file_1");
653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Open a file that doesn't exist.
673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::PlatformFileError error_code = base::PLATFORM_FILE_OK;
683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::PlatformFile file = base::CreatePlatformFile(
693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      file_path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NULL, &error_code);
713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(base::kInvalidPlatformFileValue, file);
723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, error_code);
733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Open or create a file.
753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool created = false;
763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  error_code = base::PLATFORM_FILE_OK;
773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  file = base::CreatePlatformFile(
783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      file_path, base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_READ,
793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      &created, &error_code);
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_NE(base::kInvalidPlatformFileValue, file);
813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(created);
823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(base::PLATFORM_FILE_OK, error_code);
833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::ClosePlatformFile(file);
843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Open an existing file.
863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  created = false;
873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  file = base::CreatePlatformFile(
883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      file_path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      &created, &error_code);
903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_NE(base::kInvalidPlatformFileValue, file);
913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_FALSE(created);
923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(base::PLATFORM_FILE_OK, error_code);
933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::ClosePlatformFile(file);
943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Create a file that exists.
963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  file = base::CreatePlatformFile(
973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      file_path, base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_READ,
983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      &created, &error_code);
993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(base::kInvalidPlatformFileValue, file);
1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_FALSE(created);
1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, error_code);
1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Create or overwrite a file.
1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  error_code = base::PLATFORM_FILE_OK;
1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  file = base::CreatePlatformFile(
1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      file_path, base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_READ,
1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      &created, &error_code);
1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_NE(base::kInvalidPlatformFileValue, file);
1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(created);
1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(base::PLATFORM_FILE_OK, error_code);
1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::ClosePlatformFile(file);
1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Create a delete-on-close file.
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  created = false;
1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  file_path = temp_dir.path().AppendASCII("create_file_2");
1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  file = base::CreatePlatformFile(
1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      file_path,
1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::PLATFORM_FILE_OPEN_ALWAYS |
1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::PLATFORM_FILE_DELETE_ON_CLOSE |
1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::PLATFORM_FILE_READ,
1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      &created, &error_code);
1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_NE(base::kInvalidPlatformFileValue, file);
1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(created);
1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(base::PLATFORM_FILE_OK, error_code);
1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(base::ClosePlatformFile(file));
1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_FALSE(file_util::PathExists(file_path));
1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST(PlatformFile, ReadWritePlatformFile) {
1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ScopedTempDir temp_dir;
1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  FilePath file_path = temp_dir.path().AppendASCII("read_write_file");
1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::PlatformFile file = base::CreatePlatformFile(
1353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      file_path,
1363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::PLATFORM_FILE_CREATE |
1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::PLATFORM_FILE_READ |
1383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::PLATFORM_FILE_WRITE,
1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NULL, NULL);
1403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_NE(base::kInvalidPlatformFileValue, file);
1413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  char data_to_write[] = "test";
1433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const int kTestDataSize = 4;
1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Write 0 bytes to the file.
1463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int bytes_written = WriteFully(file, 0, data_to_write, 0);
1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, bytes_written);
1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Write "test" to the file.
1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bytes_written = WriteFully(file, 0, data_to_write, kTestDataSize);
1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(kTestDataSize, bytes_written);
1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Read from EOF.
1543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  char data_read_1[32];
1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int bytes_read = ReadFully(file, kTestDataSize, data_read_1, kTestDataSize);
1563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, bytes_read);
1573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Read from somewhere in the middle of the file.
1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const int kPartialReadOffset = 1;
1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bytes_read = ReadFully(file, kPartialReadOffset, data_read_1, kTestDataSize);
1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(kTestDataSize - kPartialReadOffset, bytes_read);
1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (int i = 0; i < bytes_read; i++)
1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(data_to_write[i + kPartialReadOffset], data_read_1[i]);
1643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Read 0 bytes.
1663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bytes_read = ReadFully(file, 0, data_read_1, 0);
1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, bytes_read);
1683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Read the entire file.
1703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bytes_read = ReadFully(file, 0, data_read_1, kTestDataSize);
1713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(kTestDataSize, bytes_read);
1723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (int i = 0; i < bytes_read; i++)
1733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(data_to_write[i], data_read_1[i]);
1743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Write past the end of the file.
1763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const int kOffsetBeyondEndOfFile = 10;
1773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const int kPartialWriteLength = 2;
1783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bytes_written = WriteFully(file, kOffsetBeyondEndOfFile,
1793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                             data_to_write, kPartialWriteLength);
1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(kPartialWriteLength, bytes_written);
1813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Make sure the file was extended.
1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int64 file_size = 0;
1843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(file_util::GetFileSize(file_path, &file_size));
1853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(kOffsetBeyondEndOfFile + kPartialWriteLength, file_size);
1863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Make sure the file was zero-padded.
1883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  char data_read_2[32];
1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bytes_read = ReadFully(file, 0, data_read_2, static_cast<int>(file_size));
1903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(file_size, bytes_read);
1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (int i = 0; i < kTestDataSize; i++)
1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(data_to_write[i], data_read_2[i]);
1933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (int i = kTestDataSize; i < kOffsetBeyondEndOfFile; i++)
1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(0, data_read_2[i]);
1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (int i = kOffsetBeyondEndOfFile; i < file_size; i++)
1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(data_to_write[i - kOffsetBeyondEndOfFile], data_read_2[i]);
1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Close the file handle to allow the temp directory to be deleted.
1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::ClosePlatformFile(file);
2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST(PlatformFile, TruncatePlatformFile) {
2033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ScopedTempDir temp_dir;
2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  FilePath file_path = temp_dir.path().AppendASCII("truncate_file");
2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::PlatformFile file = base::CreatePlatformFile(
2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      file_path,
2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::PLATFORM_FILE_CREATE |
2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::PLATFORM_FILE_READ |
2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::PLATFORM_FILE_WRITE,
2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NULL, NULL);
2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_NE(base::kInvalidPlatformFileValue, file);
2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Write "test" to the file.
2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  char data_to_write[] = "test";
2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int kTestDataSize = 4;
2173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int bytes_written = WriteFully(file, 0, data_to_write, kTestDataSize);
2183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(kTestDataSize, bytes_written);
2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Extend the file.
2213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const int kExtendedFileLength = 10;
2223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int64 file_size = 0;
2233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(base::TruncatePlatformFile(file, kExtendedFileLength));
2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(file_util::GetFileSize(file_path, &file_size));
2253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(kExtendedFileLength, file_size);
2263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Make sure the file was zero-padded.
2283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  char data_read[32];
2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int bytes_read = ReadFully(file, 0, data_read, static_cast<int>(file_size));
2303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(file_size, bytes_read);
2313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (int i = 0; i < kTestDataSize; i++)
2323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(data_to_write[i], data_read[i]);
2333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (int i = kTestDataSize; i < file_size; i++)
2343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(0, data_read[i]);
2353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Truncate the file.
2373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const int kTruncatedFileLength = 2;
2383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(base::TruncatePlatformFile(file, kTruncatedFileLength));
2393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(file_util::GetFileSize(file_path, &file_size));
2403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(kTruncatedFileLength, file_size);
2413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Make sure the file was truncated.
2433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bytes_read = ReadFully(file, 0, data_read, kTestDataSize);
2443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(file_size, bytes_read);
2453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (int i = 0; i < file_size; i++)
2463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(data_to_write[i], data_read[i]);
2473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Close the file handle to allow the temp directory to be deleted.
2493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::ClosePlatformFile(file);
2503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2523345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST(PlatformFile, TouchGetInfoPlatformFile) {
2533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ScopedTempDir temp_dir;
2543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
2553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::PlatformFile file = base::CreatePlatformFile(
2563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      temp_dir.path().AppendASCII("touch_get_info_file"),
2573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::PLATFORM_FILE_CREATE |
2583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::PLATFORM_FILE_WRITE |
2593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::PLATFORM_FILE_WRITE_ATTRIBUTES,
2603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NULL, NULL);
2613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_NE(base::kInvalidPlatformFileValue, file);
2623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Get info for a newly created file.
2643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::PlatformFileInfo info;
2653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(base::GetPlatformFileInfo(file, &info));
2663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Add 2 seconds to account for possible rounding errors on
2683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // filesystems that use a 1s or 2s timestamp granularity.
2693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::Time now = base::Time::Now() + base::TimeDelta::FromSeconds(2);
2703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, info.size);
2713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_FALSE(info.is_directory);
272201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_FALSE(info.is_symbolic_link);
2733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_LE(info.last_accessed.ToInternalValue(), now.ToInternalValue());
2743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_LE(info.last_modified.ToInternalValue(), now.ToInternalValue());
2753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_LE(info.creation_time.ToInternalValue(), now.ToInternalValue());
2763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::Time creation_time = info.creation_time;
2773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Write "test" to the file.
2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  char data[] = "test";
2803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const int kTestDataSize = 4;
2813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int bytes_written = WriteFully(file, 0, data, kTestDataSize);
2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(kTestDataSize, bytes_written);
2833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Change the last_accessed and last_modified dates.
2853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // It's best to add values that are multiples of 2 (in seconds)
2863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // to the current last_accessed and last_modified times, because
2873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // FATxx uses a 2s timestamp granularity.
2883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::Time new_last_accessed =
2893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      info.last_accessed + base::TimeDelta::FromSeconds(234);
2903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::Time new_last_modified =
2913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      info.last_modified + base::TimeDelta::FromMinutes(567);
2923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(base::TouchPlatformFile(file, new_last_accessed,
2943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                      new_last_modified));
2953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Make sure the file info was updated accordingly.
2973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(base::GetPlatformFileInfo(file, &info));
2983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(info.size, kTestDataSize);
2993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_FALSE(info.is_directory);
300201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_FALSE(info.is_symbolic_link);
3013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // ext2/ext3 and HPS/HPS+ seem to have a timestamp granularity of 1s.
3033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(OS_POSIX)
3043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(info.last_accessed.ToTimeVal().tv_sec,
3053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            new_last_accessed.ToTimeVal().tv_sec);
3063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(info.last_modified.ToTimeVal().tv_sec,
3073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            new_last_modified.ToTimeVal().tv_sec);
3083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#else
3093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(info.last_accessed.ToInternalValue(),
3103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            new_last_accessed.ToInternalValue());
3113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(info.last_modified.ToInternalValue(),
3123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            new_last_modified.ToInternalValue());
3133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif
3143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(info.creation_time.ToInternalValue(),
3163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            creation_time.ToInternalValue());
3173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Close the file handle to allow the temp directory to be deleted.
3193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::ClosePlatformFile(file);
3203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
321