/*
- * Copyright 2015 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* limitations under the License.
*/
-#ifndef FOLLY_TESTUTIL_H_
-#define FOLLY_TESTUTIL_H_
+#pragma once
#include <map>
#include <string>
+
#include <folly/Range.h>
+#include <folly/ScopeGuard.h>
#include <folly/experimental/io/FsUtil.h>
namespace folly {
bool closeOnDestruction = true);
~TemporaryFile();
- // Movable, but not copiable
- TemporaryFile(TemporaryFile&&) = default;
- TemporaryFile& operator=(TemporaryFile&&) = default;
+ // Movable, but not copyable
+ TemporaryFile(TemporaryFile&& other) noexcept {
+ reset();
+ assign(other);
+ }
+
+ TemporaryFile& operator=(TemporaryFile&& other) {
+ if (this != &other) {
+ reset();
+ assign(other);
+ }
+ return *this;
+ }
+ void close();
int fd() const { return fd_; }
const fs::path& path() const;
+ void reset();
private:
Scope scope_;
bool closeOnDestruction_;
int fd_;
fs::path path_;
+
+ void assign(TemporaryFile& other) {
+ scope_ = other.scope_;
+ closeOnDestruction_ = other.closeOnDestruction_;
+ fd_ = std::exchange(other.fd_, -1);
+ path_ = other.path_;
+ }
};
/**
TemporaryDirectory(TemporaryDirectory&&) = default;
TemporaryDirectory& operator=(TemporaryDirectory&&) = default;
- const fs::path& path() const { return path_; }
+ const fs::path& path() const {
+ return *path_;
+ }
private:
Scope scope_;
- fs::path path_;
+ std::unique_ptr<fs::path> path_;
};
/**
* upon destruction, also changing back to the original working directory.
*/
class ChangeToTempDir {
-public:
+ public:
ChangeToTempDir();
~ChangeToTempDir();
const fs::path& path() const { return dir_.path(); }
-private:
+ private:
fs::path initialPath_;
TemporaryDirectory dir_;
};
+namespace detail {
+struct SavedState {
+ void* previousThreadLocalHandler;
+ int previousCrtReportMode;
+};
+SavedState disableInvalidParameters();
+void enableInvalidParameters(SavedState state);
+} // namespace detail
+
+// Ok, so fun fact: The CRT on windows will actually abort
+// on certain failed parameter validation checks in debug
+// mode rather than simply returning -1 as it does in release
+// mode. We can however, ensure consistent behavior by
+// registering our own thread-local invalid parameter handler
+// for the duration of the call, and just have that handler
+// immediately return. We also have to disable CRT asertion
+// alerts for the duration of the call, otherwise we get
+// the abort-retry-ignore window.
+template <typename Func>
+auto msvcSuppressAbortOnInvalidParams(Func func) -> decltype(func()) {
+ auto savedState = detail::disableInvalidParameters();
+ SCOPE_EXIT {
+ detail::enableInvalidParameters(savedState);
+ };
+ return func();
+}
+
/**
* Easy PCRE regex matching. Note that pattern must match the ENTIRE target,
* so use .* at the start and end of the pattern, as appropriate. See
)
namespace detail {
- bool hasPCREPatternMatch(StringPiece pattern, StringPiece target);
- bool hasNoPCREPatternMatch(StringPiece pattern, StringPiece target);
-} // namespace detail
+bool hasPCREPatternMatch(StringPiece pattern, StringPiece target);
+bool hasNoPCREPatternMatch(StringPiece pattern, StringPiece target);
+} // namespace detail
/**
* Use these patterns together with CaptureFD and EXPECT_PCRE_MATCH() to
* Great for testing logging (see also glog*Pattern()).
*/
class CaptureFD {
-private:
+ private:
struct NoOpChunkCob { void operator()(StringPiece) {} };
-public:
+
+ public:
using ChunkCob = std::function<void(folly::StringPiece)>;
/**
*/
std::string readIncremental();
-private:
+ private:
ChunkCob chunkCob_;
TemporaryFile file_;
off_t readOffset_; // for incremental reading
};
-class EnvVarSaver {
-public:
- EnvVarSaver();
- ~EnvVarSaver();
-private:
- std::map<std::string, std::string> saved_;
-};
-
-} // namespace test
-} // namespace folly
-
-#endif /* FOLLY_TESTUTIL_H_ */
+} // namespace test
+} // namespace folly