Support optional file extension in TmpFile

TmpFile can now be supplied an optional file extension. This change
was motivated by validation work using the XCode SDK Metal compiler,
which expects a source file to end with the ".metal" extension.

See
https://developer.apple.com/documentation/metal/libraries/understanding_the_metal_shading_language_filename_extension

Bug: tint:535
Change-Id: I5d44baa20ba350530ace46569e238c4627135e51
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/45720
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Arman Uguray <armansito@chromium.org>
This commit is contained in:
Arman Uguray 2021-04-13 19:07:47 +00:00 committed by Commit Bot service account
parent 5c3a7459e6
commit 66a8efc6ae
5 changed files with 39 additions and 7 deletions

View File

@ -28,7 +28,9 @@ class TmpFile {
/// Constructor.
/// Creates a new temporary file which can be written to.
/// The temporary file will be automatically deleted on destruction.
TmpFile();
/// @param extension optional file extension to use with the file. The file
/// have no extension by default.
explicit TmpFile(std::string extension = "");
/// Destructor.
/// Deletes the temporary file.

View File

@ -17,7 +17,7 @@
namespace tint {
namespace utils {
TmpFile::TmpFile() = default;
TmpFile::TmpFile(std::string) = default;
TmpFile::~TmpFile() = default;

View File

@ -15,15 +15,25 @@
#include "src/utils/tmpfile.h"
#include <unistd.h>
#include <limits>
#include "src/debug.h"
namespace tint {
namespace utils {
namespace {
std::string TmpFilePath() {
char name[] = "tint_XXXXXX";
int file = mkstemp(name);
std::string TmpFilePath(std::string ext) {
// mkstemps requires an `int` for the file extension name but STL represents
// size_t. Pre-C++20 there the behavior for unsigned-to-signed conversion
// (when the source value exceeds the representable range) is implementation
// defined. While such a large file extension is unlikely in practice, we
// enforce this here at runtime.
TINT_ASSERT(ext.length() <=
static_cast<size_t>(std::numeric_limits<int>::max()));
std::string name = "tint_XXXXXX" + ext;
int file = mkstemps(&name[0], static_cast<int>(ext.length()));
if (file != -1) {
close(file);
return name;
@ -33,7 +43,8 @@ std::string TmpFilePath() {
} // namespace
TmpFile::TmpFile() : path_(TmpFilePath()) {}
TmpFile::TmpFile(std::string extension)
: path_(TmpFilePath(std::move(extension))) {}
TmpFile::~TmpFile() {
if (!path_.empty()) {

View File

@ -66,6 +66,25 @@ TEST(TmpFileTest, WriteReadAppendDelete) {
ASSERT_FALSE(file);
}
TEST(TmpFileTest, FileExtension) {
const std::string kExt = ".foo";
std::string path;
{
TmpFile tmp(kExt);
if (!tmp) {
GTEST_SKIP() << "Unable create a temporary file";
}
path = tmp.Path();
}
ASSERT_GT(path.length(), kExt.length());
EXPECT_EQ(kExt, path.substr(path.length() - kExt.length()));
// Check the file has been deleted when it fell out of scope
std::ifstream file(path);
ASSERT_FALSE(file);
}
} // namespace
} // namespace utils
} // namespace tint

View File

@ -32,7 +32,7 @@ std::string TmpFilePath() {
} // namespace
TmpFile::TmpFile() : path_(TmpFilePath()) {}
TmpFile::TmpFile(std::string ext) : path_(TmpFilePath() + ext) {}
TmpFile::~TmpFile() {
if (!path_.empty()) {