Commit e2b8d922 authored by Allen Vicencio's avatar Allen Vicencio Committed by Commit Bot

Add TempFileManager and tests

Bug: chromium:757625
Change-Id: I0f68e43c7f9700d3d02d640d36c2d9a4523b4495
Reviewed-on: https://chromium-review.googlesource.com/894167Reviewed-by: default avatarZentaro Kavanagh <zentaro@chromium.org>
Commit-Queue: Allen Vicencio <allenvic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#534811}
parent 80d52320
...@@ -1512,6 +1512,8 @@ source_set("chromeos") { ...@@ -1512,6 +1512,8 @@ source_set("chromeos") {
"smb_client/smb_service.h", "smb_client/smb_service.h",
"smb_client/smb_service_factory.cc", "smb_client/smb_service_factory.cc",
"smb_client/smb_service_factory.h", "smb_client/smb_service_factory.h",
"smb_client/temp_file_manager.cc",
"smb_client/temp_file_manager.h",
"status/network_menu.cc", "status/network_menu.cc",
"status/network_menu.h", "status/network_menu.h",
"system/automatic_reboot_manager.cc", "system/automatic_reboot_manager.cc",
...@@ -1980,6 +1982,7 @@ source_set("unit_tests") { ...@@ -1980,6 +1982,7 @@ source_set("unit_tests") {
"settings/shutdown_policy_handler_unittest.cc", "settings/shutdown_policy_handler_unittest.cc",
"settings/stub_cros_settings_provider_unittest.cc", "settings/stub_cros_settings_provider_unittest.cc",
"smb_client/smb_service_unittest.cc", "smb_client/smb_service_unittest.cc",
"smb_client/temp_file_manager_unittest.cc",
"system/automatic_reboot_manager_unittest.cc", "system/automatic_reboot_manager_unittest.cc",
"system/device_disabling_manager_unittest.cc", "system/device_disabling_manager_unittest.cc",
"system_logs/single_debug_daemon_log_source_unittest.cc", "system_logs/single_debug_daemon_log_source_unittest.cc",
......
// Copyright 2017 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 "chrome/browser/chromeos/smb_client/temp_file_manager.h"
#include <stdlib.h>
#include <unistd.h>
#include <memory>
#include <string>
#include <vector>
#include "base/files/file_util.h"
namespace chromeos {
namespace smb_client {
TempFileManager::TempFileManager() {
CHECK(temp_dir_.CreateUniqueTempDir());
}
TempFileManager::~TempFileManager() = default;
const base::FilePath& TempFileManager::GetTempDirectoryPath() const {
return temp_dir_.GetPath();
}
base::ScopedFD TempFileManager::CreateTempFile(
const std::vector<uint8_t>& data) {
base::ScopedFD temp_fd = CreateTempFile();
// Write the data into the newly created file.
if (!base::WriteFileDescriptor(temp_fd.get(),
reinterpret_cast<const char*>(data.data()),
data.size())) {
LOG(ERROR) << "Error writing to temporary file";
temp_fd.reset();
return temp_fd;
}
// Seek the file descriptor to the start of the file in preparation for
// reading.
if (lseek(temp_fd.get(), 0, SEEK_SET) < 0) {
LOG(ERROR) << "Error seeking to beginning of temporary file";
temp_fd.reset();
return temp_fd;
}
return temp_fd;
}
base::ScopedFD TempFileManager::CreateTempFile() {
const std::string str = temp_dir_.GetPath().Append("XXXXXX").value();
// Make sure that the string we are passing is null-terminated.
std::unique_ptr<char[]> file_path = std::make_unique<char[]>(str.size() + 1);
memcpy(file_path.get(), str.c_str(), str.size());
file_path[str.size()] = '\0';
// mkstemp() modifies the passed in array.
base::ScopedFD temp_fd(HANDLE_EINTR(mkstemp(file_path.get())));
if (!temp_fd.is_valid()) {
LOG(ERROR) << "mkstemp failed to create a temporary file";
temp_fd.reset();
return temp_fd;
}
// Unlink causes the file to be deleted when the file descriptor is closed.
if (unlink(file_path.get()) != 0) {
LOG(ERROR) << "Failed to unlink temporary file: " << file_path.get();
temp_fd.reset();
return temp_fd;
}
return temp_fd;
}
} // namespace smb_client
} // namespace chromeos
// Copyright 2017 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.
#ifndef CHROME_BROWSER_CHROMEOS_SMB_CLIENT_TEMP_FILE_MANAGER_H_
#define CHROME_BROWSER_CHROMEOS_SMB_CLIENT_TEMP_FILE_MANAGER_H_
#include <vector>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
namespace chromeos {
namespace smb_client {
// Helper class to handle construction and deletion of a temporary directory
// containing temporary files.
class TempFileManager {
public:
TempFileManager();
~TempFileManager();
// Returns the path of the temporary directory.
const base::FilePath& GetTempDirectoryPath() const;
// Creates a temporary file in temp_dir_ path and writes in |data|. Before
// returning, this seeks to the beginning of the file in preparation for
// reading. This also calls unlink() on the created file. Returns a file
// descriptor which will be invalid on failure.
base::ScopedFD CreateTempFile(const std::vector<uint8_t>& data);
private:
// Creates a temporary file in temp_dir_ path. This also calls unlink() on the
// created file. Returns a file descriptor which will be invalid on failure.
base::ScopedFD CreateTempFile();
// Scoped class that handles deletion of the temporary directory.
base::ScopedTempDir temp_dir_;
DISALLOW_COPY_AND_ASSIGN(TempFileManager);
};
} // namespace smb_client
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_SMB_CLIENT_TEMP_FILE_MANAGER_H_
// Copyright 2017 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 "chrome/browser/chromeos/smb_client/temp_file_manager.h"
#include <string>
#include <vector>
#include "base/files/file_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace smb_client {
namespace {
// Helper method to get the current offset of a file descriptor |fd|. Returns
// the offset from the beginning of the file.
int64_t GetCurrentOffset(int32_t fd) {
return lseek(fd, 0, SEEK_CUR);
}
} // namespace
class TempFileManagerTest : public testing::Test {
public:
TempFileManagerTest() = default;
~TempFileManagerTest() override = default;
private:
DISALLOW_COPY_AND_ASSIGN(TempFileManagerTest);
};
// Should properly create a path when the object is created.
TEST_F(TempFileManagerTest, ShouldCreatePath) {
TempFileManager file_manager;
const base::FilePath& path = file_manager.GetTempDirectoryPath();
EXPECT_FALSE(path.empty());
EXPECT_TRUE(base::PathExists(path));
}
// Path should be deleted after TempFileManager is cleaned up.
TEST_F(TempFileManagerTest, PathShouldBeDeleted) {
std::string path;
{
TempFileManager file_manager;
path = file_manager.GetTempDirectoryPath().value();
EXPECT_TRUE(base::PathExists(base::FilePath(path)));
}
EXPECT_FALSE(base::PathExists(base::FilePath(path)));
}
// Should properly create a file with data and return a valid ScopedFD.
TEST_F(TempFileManagerTest, ShouldCreateFile) {
std::vector<uint8_t> data = {0, 1, 2, 3, 4, 5, 6};
TempFileManager file_manager;
base::ScopedFD fd = file_manager.CreateTempFile(data);
EXPECT_TRUE(fd.is_valid());
}
// Should properly unlink directory path even if a file descriptor is open.
TEST_F(TempFileManagerTest, FileShouldBeUnlinked) {
std::string path;
{
std::vector<uint8_t> data = {0, 1, 2, 3, 4, 5, 6};
TempFileManager file_manager;
path = file_manager.GetTempDirectoryPath().value();
base::ScopedFD fd = file_manager.CreateTempFile(data);
}
// Directory should be unlinked.
EXPECT_FALSE(base::PathExists(base::FilePath(path)));
}
// CreateFile should properly write the data into a file and seek back to the
// beginning of the file.
TEST_F(TempFileManagerTest, WriteFileSucceeds) {
std::vector<uint8_t> expected = {0, 1, 2, 3, 4, 5, 6};
TempFileManager file_manager;
base::ScopedFD fd = file_manager.CreateTempFile(expected);
// Expect the current offset to be at the beginning of the file.
EXPECT_EQ(0, GetCurrentOffset(fd.get()));
// Read back the data written and ensure that it is the same.
std::vector<uint8_t> actual(expected.size());
EXPECT_TRUE(base::ReadFromFD(fd.get(), reinterpret_cast<char*>(actual.data()),
actual.size()));
EXPECT_EQ(expected, actual);
}
} // namespace smb_client
} // namespace chromeos
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