Skip to content

Commit

Permalink
[FileUtil] Test thread-safety of temp file APIs.
Browse files Browse the repository at this point in the history
Ruling out https://crbug.com/826408#c17 as the source of the issue.

R=thestig@chromium.org

Bug: 826408
Change-Id: I00396084d674fa2f700eb917300280b6eed1684d
Reviewed-on: https://chromium-review.googlesource.com/1072030
Commit-Queue: Gabriel Charette <gab@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Cr-Commit-Position: refs/heads/master@{#561666}
  • Loading branch information
Gabriel Charette authored and Commit Bot committed May 24, 2018
1 parent f66d57a commit 20a5f39
Showing 1 changed file with 60 additions and 0 deletions.
60 changes: 60 additions & 0 deletions base/files/file_util_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <stddef.h>
#include <stdint.h>
#include <stdio.h>

#include <algorithm>
#include <fstream>
Expand All @@ -25,6 +26,7 @@
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/files/scoped_temp_dir.h"
#include "base/guid.h"
#include "base/macros.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
Expand All @@ -34,6 +36,7 @@
#include "base/test/test_file_util.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/multiprocess_func_list.h"
Expand Down Expand Up @@ -3637,6 +3640,63 @@ TEST_F(FileUtilTest, NonExistentContentUriTest) {
}
#endif

// Test that temp files obtained racily are all unique (no interference between
// threads). Mimics file operations in DoLaunchChildTestProcess() to rule out
// thread-safety issues @ https://crbug.com/826408#c17.
TEST(FileUtilMultiThreadedTest, MultiThreadedTempFiles) {
constexpr int kNumThreads = 64;
constexpr int kNumWritesPerThread = 32;

std::unique_ptr<Thread> threads[kNumThreads];
for (auto& thread : threads) {
thread = std::make_unique<Thread>("test worker");
thread->Start();
}

// Wait until all threads are started for max parallelism.
for (auto& thread : threads)
thread->WaitUntilThreadStarted();

const RepeatingClosure open_write_close_read = BindRepeating([]() {
FilePath output_filename;
ScopedFILE output_file(CreateAndOpenTemporaryFile(&output_filename));
EXPECT_TRUE(output_file);

const std::string content = GenerateGUID();
#if defined(OS_WIN)
HANDLE handle =
reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(output_file.get())));
DWORD bytes_written = 0;
::WriteFile(handle, content.c_str(), content.length(), &bytes_written,
NULL);
EXPECT_EQ(content.length(), bytes_written);
#else
::write(::fileno(output_file.get()), content.c_str(), content.length());
#endif
::fflush(output_file.get());
output_file.reset();

std::string output_file_contents;
EXPECT_TRUE(ReadFileToString(output_filename, &output_file_contents))
<< output_filename;

EXPECT_EQ(content, output_file_contents);

DeleteFile(output_filename, false);
});

// Post tasks to each thread in a round-robin fashion to ensure as much
// parallelism as possible.
for (int i = 0; i < kNumWritesPerThread; ++i) {
for (auto& thread : threads) {
thread->task_runner()->PostTask(FROM_HERE, open_write_close_read);
}
}

for (auto& thread : threads)
thread->Stop();
}

#if defined(OS_POSIX) || defined(OS_FUCHSIA)

TEST(ScopedFD, ScopedFDDoesClose) {
Expand Down

0 comments on commit 20a5f39

Please sign in to comment.