base_file_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/download/base_file.h"
6
7#include "base/file_util.h"
8#include "base/files/scoped_temp_dir.h"
9#include "base/logging.h"
10#include "base/message_loop/message_loop.h"
11#include "base/strings/string_number_conversions.h"
12#include "base/test/test_file_util.h"
13#include "content/browser/browser_thread_impl.h"
14#include "content/public/browser/download_interrupt_reasons.h"
15#include "crypto/secure_hash.h"
16#include "crypto/sha2.h"
17#include "net/base/file_stream.h"
18#include "net/base/mock_file_stream.h"
19#include "testing/gtest/include/gtest/gtest.h"
20
21namespace content {
22namespace {
23
24const char kTestData1[] = "Let's write some data to the file!\n";
25const char kTestData2[] = "Writing more data.\n";
26const char kTestData3[] = "Final line.";
27const char kTestData4[] = "supercalifragilisticexpialidocious";
28const int kTestDataLength1 = arraysize(kTestData1) - 1;
29const int kTestDataLength2 = arraysize(kTestData2) - 1;
30const int kTestDataLength3 = arraysize(kTestData3) - 1;
31const int kTestDataLength4 = arraysize(kTestData4) - 1;
32const int kElapsedTimeSeconds = 5;
33const base::TimeDelta kElapsedTimeDelta = base::TimeDelta::FromSeconds(
34    kElapsedTimeSeconds);
35
36}  // namespace
37
38class BaseFileTest : public testing::Test {
39 public:
40  static const unsigned char kEmptySha256Hash[crypto::kSHA256Length];
41
42  BaseFileTest()
43      : expect_file_survives_(false),
44        expect_in_progress_(true),
45        expected_error_(DOWNLOAD_INTERRUPT_REASON_NONE),
46        file_thread_(BrowserThread::FILE, &message_loop_) {
47  }
48
49  virtual void SetUp() {
50    ResetHash();
51    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
52    base_file_.reset(new BaseFile(base::FilePath(),
53                                  GURL(),
54                                  GURL(),
55                                  0,
56                                  false,
57                                  std::string(),
58                                  scoped_ptr<net::FileStream>(),
59                                  net::BoundNetLog()));
60  }
61
62  virtual void TearDown() {
63    EXPECT_FALSE(base_file_->in_progress());
64    if (!expected_error_) {
65      EXPECT_EQ(static_cast<int64>(expected_data_.size()),
66                base_file_->bytes_so_far());
67    }
68
69    base::FilePath full_path = base_file_->full_path();
70
71    if (!expected_data_.empty() && !expected_error_) {
72      // Make sure the data has been properly written to disk.
73      std::string disk_data;
74      EXPECT_TRUE(base::ReadFileToString(full_path, &disk_data));
75      EXPECT_EQ(expected_data_, disk_data);
76    }
77
78    // Make sure the mock BrowserThread outlives the BaseFile to satisfy
79    // thread checks inside it.
80    base_file_.reset();
81
82    EXPECT_EQ(expect_file_survives_, base::PathExists(full_path));
83  }
84
85  void ResetHash() {
86    secure_hash_.reset(crypto::SecureHash::Create(crypto::SecureHash::SHA256));
87    memcpy(sha256_hash_, kEmptySha256Hash, crypto::kSHA256Length);
88  }
89
90  void UpdateHash(const char* data, size_t length) {
91    secure_hash_->Update(data, length);
92  }
93
94  std::string GetFinalHash() {
95    std::string hash;
96    secure_hash_->Finish(sha256_hash_, crypto::kSHA256Length);
97    hash.assign(reinterpret_cast<const char*>(sha256_hash_),
98                sizeof(sha256_hash_));
99    return hash;
100  }
101
102  void MakeFileWithHash() {
103    base_file_.reset(new BaseFile(base::FilePath(),
104                                  GURL(),
105                                  GURL(),
106                                  0,
107                                  true,
108                                  std::string(),
109                                  scoped_ptr<net::FileStream>(),
110                                  net::BoundNetLog()));
111  }
112
113  bool InitializeFile() {
114    DownloadInterruptReason result = base_file_->Initialize(temp_dir_.path());
115    EXPECT_EQ(expected_error_, result);
116    return result == DOWNLOAD_INTERRUPT_REASON_NONE;
117  }
118
119  bool AppendDataToFile(const std::string& data) {
120    EXPECT_EQ(expect_in_progress_, base_file_->in_progress());
121    DownloadInterruptReason result =
122        base_file_->AppendDataToFile(data.data(), data.size());
123    if (result == DOWNLOAD_INTERRUPT_REASON_NONE)
124      EXPECT_TRUE(expect_in_progress_) << " result = " << result;
125
126    EXPECT_EQ(expected_error_, result);
127    if (base_file_->in_progress()) {
128      expected_data_ += data;
129      if (expected_error_ == DOWNLOAD_INTERRUPT_REASON_NONE) {
130        EXPECT_EQ(static_cast<int64>(expected_data_.size()),
131                  base_file_->bytes_so_far());
132      }
133    }
134    return result == DOWNLOAD_INTERRUPT_REASON_NONE;
135  }
136
137  void set_expected_data(const std::string& data) { expected_data_ = data; }
138
139  // Helper functions.
140  // Create a file.  Returns the complete file path.
141  base::FilePath CreateTestFile() {
142    base::FilePath file_name;
143    BaseFile file(base::FilePath(),
144                  GURL(),
145                  GURL(),
146                  0,
147                  false,
148                  std::string(),
149                  scoped_ptr<net::FileStream>(),
150                  net::BoundNetLog());
151
152    EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
153              file.Initialize(temp_dir_.path()));
154    file_name = file.full_path();
155    EXPECT_NE(base::FilePath::StringType(), file_name.value());
156
157    EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
158              file.AppendDataToFile(kTestData4, kTestDataLength4));
159
160    // Keep the file from getting deleted when existing_file_name is deleted.
161    file.Detach();
162
163    return file_name;
164  }
165
166  // Create a file with the specified file name.
167  void CreateFileWithName(const base::FilePath& file_name) {
168    EXPECT_NE(base::FilePath::StringType(), file_name.value());
169    BaseFile duplicate_file(file_name,
170                            GURL(),
171                            GURL(),
172                            0,
173                            false,
174                            std::string(),
175                            scoped_ptr<net::FileStream>(),
176                            net::BoundNetLog());
177    EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
178              duplicate_file.Initialize(temp_dir_.path()));
179    // Write something into it.
180    duplicate_file.AppendDataToFile(kTestData4, kTestDataLength4);
181    // Detach the file so it isn't deleted on destruction of |duplicate_file|.
182    duplicate_file.Detach();
183  }
184
185  int64 CurrentSpeedAtTime(base::TimeTicks current_time) {
186    EXPECT_TRUE(base_file_.get());
187    return base_file_->CurrentSpeedAtTime(current_time);
188  }
189
190  base::TimeTicks StartTick() {
191    EXPECT_TRUE(base_file_.get());
192    return base_file_->start_tick_;
193  }
194
195  void set_expected_error(DownloadInterruptReason err) {
196    expected_error_ = err;
197  }
198
199 protected:
200  linked_ptr<net::testing::MockFileStream> mock_file_stream_;
201
202  // BaseClass instance we are testing.
203  scoped_ptr<BaseFile> base_file_;
204
205  // Temporary directory for renamed downloads.
206  base::ScopedTempDir temp_dir_;
207
208  // Expect the file to survive deletion of the BaseFile instance.
209  bool expect_file_survives_;
210
211  // Expect the file to be in progress.
212  bool expect_in_progress_;
213
214  // Hash calculator.
215  scoped_ptr<crypto::SecureHash> secure_hash_;
216
217  unsigned char sha256_hash_[crypto::kSHA256Length];
218
219 private:
220  // Keep track of what data should be saved to the disk file.
221  std::string expected_data_;
222  DownloadInterruptReason expected_error_;
223
224  // Mock file thread to satisfy debug checks in BaseFile.
225  base::MessageLoop message_loop_;
226  BrowserThreadImpl file_thread_;
227};
228
229// This will initialize the entire array to zero.
230const unsigned char BaseFileTest::kEmptySha256Hash[] = { 0 };
231
232// Test the most basic scenario: just create the object and do a sanity check
233// on all its accessors. This is actually a case that rarely happens
234// in production, where we would at least Initialize it.
235TEST_F(BaseFileTest, CreateDestroy) {
236  EXPECT_EQ(base::FilePath().value(), base_file_->full_path().value());
237}
238
239// Cancel the download explicitly.
240TEST_F(BaseFileTest, Cancel) {
241  ASSERT_TRUE(InitializeFile());
242  EXPECT_TRUE(base::PathExists(base_file_->full_path()));
243  base_file_->Cancel();
244  EXPECT_FALSE(base::PathExists(base_file_->full_path()));
245  EXPECT_NE(base::FilePath().value(), base_file_->full_path().value());
246}
247
248// Write data to the file and detach it, so it doesn't get deleted
249// automatically when base_file_ is destructed.
250TEST_F(BaseFileTest, WriteAndDetach) {
251  ASSERT_TRUE(InitializeFile());
252  ASSERT_TRUE(AppendDataToFile(kTestData1));
253  base_file_->Finish();
254  base_file_->Detach();
255  expect_file_survives_ = true;
256}
257
258// Write data to the file and detach it, and calculate its sha256 hash.
259TEST_F(BaseFileTest, WriteWithHashAndDetach) {
260  // Calculate the final hash.
261  ResetHash();
262  UpdateHash(kTestData1, kTestDataLength1);
263  std::string expected_hash = GetFinalHash();
264  std::string expected_hash_hex =
265      base::HexEncode(expected_hash.data(), expected_hash.size());
266
267  MakeFileWithHash();
268  ASSERT_TRUE(InitializeFile());
269  ASSERT_TRUE(AppendDataToFile(kTestData1));
270  base_file_->Finish();
271
272  std::string hash;
273  base_file_->GetHash(&hash);
274  EXPECT_EQ("0B2D3F3F7943AD64B860DF94D05CB56A8A97C6EC5768B5B70B930C5AA7FA9ADE",
275            expected_hash_hex);
276  EXPECT_EQ(expected_hash_hex, base::HexEncode(hash.data(), hash.size()));
277
278  base_file_->Detach();
279  expect_file_survives_ = true;
280}
281
282// Rename the file after writing to it, then detach.
283TEST_F(BaseFileTest, WriteThenRenameAndDetach) {
284  ASSERT_TRUE(InitializeFile());
285
286  base::FilePath initial_path(base_file_->full_path());
287  EXPECT_TRUE(base::PathExists(initial_path));
288  base::FilePath new_path(temp_dir_.path().AppendASCII("NewFile"));
289  EXPECT_FALSE(base::PathExists(new_path));
290
291  ASSERT_TRUE(AppendDataToFile(kTestData1));
292
293  EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, base_file_->Rename(new_path));
294  EXPECT_FALSE(base::PathExists(initial_path));
295  EXPECT_TRUE(base::PathExists(new_path));
296
297  base_file_->Finish();
298  base_file_->Detach();
299  expect_file_survives_ = true;
300}
301
302// Write data to the file once.
303TEST_F(BaseFileTest, SingleWrite) {
304  ASSERT_TRUE(InitializeFile());
305  ASSERT_TRUE(AppendDataToFile(kTestData1));
306  base_file_->Finish();
307}
308
309// Write data to the file multiple times.
310TEST_F(BaseFileTest, MultipleWrites) {
311  ASSERT_TRUE(InitializeFile());
312  ASSERT_TRUE(AppendDataToFile(kTestData1));
313  ASSERT_TRUE(AppendDataToFile(kTestData2));
314  ASSERT_TRUE(AppendDataToFile(kTestData3));
315  std::string hash;
316  EXPECT_FALSE(base_file_->GetHash(&hash));
317  base_file_->Finish();
318}
319
320// Write data to the file once and calculate its sha256 hash.
321TEST_F(BaseFileTest, SingleWriteWithHash) {
322  // Calculate the final hash.
323  ResetHash();
324  UpdateHash(kTestData1, kTestDataLength1);
325  std::string expected_hash = GetFinalHash();
326  std::string expected_hash_hex =
327      base::HexEncode(expected_hash.data(), expected_hash.size());
328
329  MakeFileWithHash();
330  ASSERT_TRUE(InitializeFile());
331  // Can get partial hash states before Finish() is called.
332  EXPECT_STRNE(std::string().c_str(), base_file_->GetHashState().c_str());
333  ASSERT_TRUE(AppendDataToFile(kTestData1));
334  EXPECT_STRNE(std::string().c_str(), base_file_->GetHashState().c_str());
335  base_file_->Finish();
336
337  std::string hash;
338  base_file_->GetHash(&hash);
339  EXPECT_EQ(expected_hash_hex, base::HexEncode(hash.data(), hash.size()));
340}
341
342// Write data to the file multiple times and calculate its sha256 hash.
343TEST_F(BaseFileTest, MultipleWritesWithHash) {
344  // Calculate the final hash.
345  ResetHash();
346  UpdateHash(kTestData1, kTestDataLength1);
347  UpdateHash(kTestData2, kTestDataLength2);
348  UpdateHash(kTestData3, kTestDataLength3);
349  std::string expected_hash = GetFinalHash();
350  std::string expected_hash_hex =
351      base::HexEncode(expected_hash.data(), expected_hash.size());
352
353  std::string hash;
354  MakeFileWithHash();
355  ASSERT_TRUE(InitializeFile());
356  ASSERT_TRUE(AppendDataToFile(kTestData1));
357  ASSERT_TRUE(AppendDataToFile(kTestData2));
358  ASSERT_TRUE(AppendDataToFile(kTestData3));
359  // No hash before Finish() is called.
360  EXPECT_FALSE(base_file_->GetHash(&hash));
361  base_file_->Finish();
362
363  EXPECT_TRUE(base_file_->GetHash(&hash));
364  EXPECT_EQ("CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8",
365            expected_hash_hex);
366  EXPECT_EQ(expected_hash_hex, base::HexEncode(hash.data(), hash.size()));
367}
368
369// Write data to the file multiple times, interrupt it, and continue using
370// another file.  Calculate the resulting combined sha256 hash.
371TEST_F(BaseFileTest, MultipleWritesInterruptedWithHash) {
372  // Calculate the final hash.
373  ResetHash();
374  UpdateHash(kTestData1, kTestDataLength1);
375  UpdateHash(kTestData2, kTestDataLength2);
376  UpdateHash(kTestData3, kTestDataLength3);
377  std::string expected_hash = GetFinalHash();
378  std::string expected_hash_hex =
379      base::HexEncode(expected_hash.data(), expected_hash.size());
380
381  MakeFileWithHash();
382  ASSERT_TRUE(InitializeFile());
383  // Write some data
384  ASSERT_TRUE(AppendDataToFile(kTestData1));
385  ASSERT_TRUE(AppendDataToFile(kTestData2));
386  // Get the hash state and file name.
387  std::string hash_state;
388  hash_state = base_file_->GetHashState();
389  // Finish the file.
390  base_file_->Finish();
391
392  base::FilePath new_file_path(temp_dir_.path().Append(
393      base::FilePath(FILE_PATH_LITERAL("second_file"))));
394
395  ASSERT_TRUE(base::CopyFile(base_file_->full_path(), new_file_path));
396
397  // Create another file
398  BaseFile second_file(new_file_path,
399                       GURL(),
400                       GURL(),
401                       base_file_->bytes_so_far(),
402                       true,
403                       hash_state,
404                       scoped_ptr<net::FileStream>(),
405                       net::BoundNetLog());
406  ASSERT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
407            second_file.Initialize(base::FilePath()));
408  std::string data(kTestData3);
409  EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
410            second_file.AppendDataToFile(data.data(), data.size()));
411  second_file.Finish();
412
413  std::string hash;
414  EXPECT_TRUE(second_file.GetHash(&hash));
415  // This will fail until getting the hash state is supported in SecureHash.
416  EXPECT_STREQ(expected_hash_hex.c_str(),
417               base::HexEncode(hash.data(), hash.size()).c_str());
418}
419
420// Rename the file after all writes to it.
421TEST_F(BaseFileTest, WriteThenRename) {
422  ASSERT_TRUE(InitializeFile());
423
424  base::FilePath initial_path(base_file_->full_path());
425  EXPECT_TRUE(base::PathExists(initial_path));
426  base::FilePath new_path(temp_dir_.path().AppendASCII("NewFile"));
427  EXPECT_FALSE(base::PathExists(new_path));
428
429  ASSERT_TRUE(AppendDataToFile(kTestData1));
430
431  EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
432            base_file_->Rename(new_path));
433  EXPECT_FALSE(base::PathExists(initial_path));
434  EXPECT_TRUE(base::PathExists(new_path));
435
436  base_file_->Finish();
437}
438
439// Rename the file while the download is still in progress.
440TEST_F(BaseFileTest, RenameWhileInProgress) {
441  ASSERT_TRUE(InitializeFile());
442
443  base::FilePath initial_path(base_file_->full_path());
444  EXPECT_TRUE(base::PathExists(initial_path));
445  base::FilePath new_path(temp_dir_.path().AppendASCII("NewFile"));
446  EXPECT_FALSE(base::PathExists(new_path));
447
448  ASSERT_TRUE(AppendDataToFile(kTestData1));
449
450  EXPECT_TRUE(base_file_->in_progress());
451  EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, base_file_->Rename(new_path));
452  EXPECT_FALSE(base::PathExists(initial_path));
453  EXPECT_TRUE(base::PathExists(new_path));
454
455  ASSERT_TRUE(AppendDataToFile(kTestData2));
456
457  base_file_->Finish();
458}
459
460// Test that a failed rename reports the correct error.
461TEST_F(BaseFileTest, RenameWithError) {
462  ASSERT_TRUE(InitializeFile());
463
464  // TestDir is a subdirectory in |temp_dir_| that we will make read-only so
465  // that the rename will fail.
466  base::FilePath test_dir(temp_dir_.path().AppendASCII("TestDir"));
467  ASSERT_TRUE(base::CreateDirectory(test_dir));
468
469  base::FilePath new_path(test_dir.AppendASCII("TestFile"));
470  EXPECT_FALSE(base::PathExists(new_path));
471
472  {
473    file_util::PermissionRestorer restore_permissions_for(test_dir);
474    ASSERT_TRUE(file_util::MakeFileUnwritable(test_dir));
475    EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED,
476              base_file_->Rename(new_path));
477  }
478
479  base_file_->Finish();
480}
481
482// Write data to the file multiple times.
483TEST_F(BaseFileTest, MultipleWritesWithError) {
484  base::FilePath path;
485  ASSERT_TRUE(base::CreateTemporaryFile(&path));
486  // Create a new file stream.  scoped_ptr takes ownership and passes it to
487  // BaseFile; we use the pointer anyway and rely on the BaseFile not
488  // deleting the MockFileStream until the BaseFile is reset.
489  net::testing::MockFileStream* mock_file_stream(
490      new net::testing::MockFileStream(NULL));
491  scoped_ptr<net::FileStream> mock_file_stream_scoped_ptr(mock_file_stream);
492
493  ASSERT_EQ(0,
494            mock_file_stream->OpenSync(
495                path,
496                base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE));
497
498  // Copy of mock_file_stream; we pass ownership and rely on the BaseFile
499  // not deleting it until it is reset.
500
501  base_file_.reset(new BaseFile(mock_file_stream->get_path(),
502                                GURL(),
503                                GURL(),
504                                0,
505                                false,
506                                std::string(),
507                                mock_file_stream_scoped_ptr.Pass(),
508                                net::BoundNetLog()));
509  ASSERT_TRUE(InitializeFile());
510  ASSERT_TRUE(AppendDataToFile(kTestData1));
511  ASSERT_TRUE(AppendDataToFile(kTestData2));
512  mock_file_stream->set_forced_error(net::ERR_ACCESS_DENIED);
513  set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED);
514  ASSERT_FALSE(AppendDataToFile(kTestData3));
515  std::string hash;
516  EXPECT_FALSE(base_file_->GetHash(&hash));
517  base_file_->Finish();
518}
519
520// Try to write to uninitialized file.
521TEST_F(BaseFileTest, UninitializedFile) {
522  expect_in_progress_ = false;
523  set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
524  EXPECT_FALSE(AppendDataToFile(kTestData1));
525}
526
527// Create two |BaseFile|s with the same file, and attempt to write to both.
528// Overwrite base_file_ with another file with the same name and
529// non-zero contents, and make sure the last file to close 'wins'.
530TEST_F(BaseFileTest, DuplicateBaseFile) {
531  ASSERT_TRUE(InitializeFile());
532
533  // Create another |BaseFile| referring to the file that |base_file_| owns.
534  CreateFileWithName(base_file_->full_path());
535
536  ASSERT_TRUE(AppendDataToFile(kTestData1));
537  base_file_->Finish();
538}
539
540// Create a file and append to it.
541TEST_F(BaseFileTest, AppendToBaseFile) {
542  // Create a new file.
543  base::FilePath existing_file_name = CreateTestFile();
544
545  set_expected_data(kTestData4);
546
547  // Use the file we've just created.
548  base_file_.reset(new BaseFile(existing_file_name,
549                                GURL(),
550                                GURL(),
551                                kTestDataLength4,
552                                false,
553                                std::string(),
554                                scoped_ptr<net::FileStream>(),
555                                net::BoundNetLog()));
556
557  ASSERT_TRUE(InitializeFile());
558
559  const base::FilePath file_name = base_file_->full_path();
560  EXPECT_NE(base::FilePath::StringType(), file_name.value());
561
562  // Write into the file.
563  EXPECT_TRUE(AppendDataToFile(kTestData1));
564
565  base_file_->Finish();
566  base_file_->Detach();
567  expect_file_survives_ = true;
568}
569
570// Create a read-only file and attempt to write to it.
571TEST_F(BaseFileTest, ReadonlyBaseFile) {
572  // Create a new file.
573  base::FilePath readonly_file_name = CreateTestFile();
574
575  // Restore permissions to the file when we are done with this test.
576  file_util::PermissionRestorer restore_permissions(readonly_file_name);
577
578  // Make it read-only.
579  EXPECT_TRUE(file_util::MakeFileUnwritable(readonly_file_name));
580
581  // Try to overwrite it.
582  base_file_.reset(new BaseFile(readonly_file_name,
583                                GURL(),
584                                GURL(),
585                                0,
586                                false,
587                                std::string(),
588                                scoped_ptr<net::FileStream>(),
589                                net::BoundNetLog()));
590
591  expect_in_progress_ = false;
592  set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED);
593  EXPECT_FALSE(InitializeFile());
594
595  const base::FilePath file_name = base_file_->full_path();
596  EXPECT_NE(base::FilePath::StringType(), file_name.value());
597
598  // Write into the file.
599  set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
600  EXPECT_FALSE(AppendDataToFile(kTestData1));
601
602  base_file_->Finish();
603  base_file_->Detach();
604  expect_file_survives_ = true;
605}
606
607TEST_F(BaseFileTest, IsEmptyHash) {
608  std::string empty(crypto::kSHA256Length, '\x00');
609  EXPECT_TRUE(BaseFile::IsEmptyHash(empty));
610  std::string not_empty(crypto::kSHA256Length, '\x01');
611  EXPECT_FALSE(BaseFile::IsEmptyHash(not_empty));
612  EXPECT_FALSE(BaseFile::IsEmptyHash(std::string()));
613
614  std::string also_not_empty = empty;
615  also_not_empty[crypto::kSHA256Length - 1] = '\x01';
616  EXPECT_FALSE(BaseFile::IsEmptyHash(also_not_empty));
617}
618
619// Test that a temporary file is created in the default download directory.
620TEST_F(BaseFileTest, CreatedInDefaultDirectory) {
621  ASSERT_TRUE(base_file_->full_path().empty());
622  ASSERT_TRUE(InitializeFile());
623  EXPECT_FALSE(base_file_->full_path().empty());
624
625  // On Windows, CreateTemporaryFileInDir() will cause a path with short names
626  // to be expanded into a path with long names. Thus temp_dir.path() might not
627  // be a string-wise match to base_file_->full_path().DirName() even though
628  // they are in the same directory.
629  base::FilePath temp_file;
630  ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file));
631  ASSERT_FALSE(temp_file.empty());
632  EXPECT_STREQ(temp_file.DirName().value().c_str(),
633               base_file_->full_path().DirName().value().c_str());
634  base_file_->Finish();
635}
636
637}  // namespace content
638