PageRenderTime 26ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/test/gtest-extra-test.cc

https://github.com/cfanzp008/cppformat
C++ | 834 lines | 646 code | 104 blank | 84 comment | 26 complexity | 2b56d2c7a88b7baf8f7befb1f3ab0653 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /*
  2. Tests of custom Google Test assertions.
  3. Copyright (c) 2012-2014, Victor Zverovich
  4. All rights reserved.
  5. Redistribution and use in source and binary forms, with or without
  6. modification, are permitted provided that the following conditions are met:
  7. 1. Redistributions of source code must retain the above copyright notice, this
  8. list of conditions and the following disclaimer.
  9. 2. Redistributions in binary form must reproduce the above copyright notice,
  10. this list of conditions and the following disclaimer in the documentation
  11. and/or other materials provided with the distribution.
  12. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  13. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  14. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  15. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  16. ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  17. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  18. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  19. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  20. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  21. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  22. */
  23. #include "gtest-extra.h"
  24. #include <cstring>
  25. #include <algorithm>
  26. #include <stdexcept>
  27. #include <gtest/gtest-spi.h>
  28. #if defined(_WIN32) && !defined(__MINGW32__)
  29. # include <crtdbg.h> // for _CrtSetReportMode
  30. #endif // _WIN32
  31. namespace {
  32. #if defined(_WIN32) && !defined(__MINGW32__)
  33. // Suppresses Windows assertions on invalid file descriptors, making
  34. // POSIX functions return proper error codes instead of crashing on Windows.
  35. class SuppressAssert {
  36. private:
  37. _invalid_parameter_handler original_handler_;
  38. int original_report_mode_;
  39. static void InvalidParameterHandler(const wchar_t *,
  40. const wchar_t *, const wchar_t *, unsigned , uintptr_t) {}
  41. public:
  42. SuppressAssert()
  43. : original_handler_(_set_invalid_parameter_handler(InvalidParameterHandler)),
  44. original_report_mode_(_CrtSetReportMode(_CRT_ASSERT, 0)) {
  45. }
  46. ~SuppressAssert() {
  47. _set_invalid_parameter_handler(original_handler_);
  48. _CrtSetReportMode(_CRT_ASSERT, original_report_mode_);
  49. }
  50. };
  51. # define SUPPRESS_ASSERT(statement) { SuppressAssert sa; statement; }
  52. // Fix "secure" warning about using fopen without defining
  53. // _CRT_SECURE_NO_WARNINGS.
  54. FILE *OpenFile(const char *filename, const char *mode) {
  55. FILE *f = 0;
  56. errno = fopen_s(&f, filename, mode);
  57. return f;
  58. }
  59. #define fopen OpenFile
  60. #else
  61. # define SUPPRESS_ASSERT(statement) statement
  62. using std::fopen;
  63. #endif // _WIN32
  64. #define EXPECT_SYSTEM_ERROR_NOASSERT(statement, error_code, message) \
  65. EXPECT_SYSTEM_ERROR(SUPPRESS_ASSERT(statement), error_code, message)
  66. // Tests that assertion macros evaluate their arguments exactly once.
  67. class SingleEvaluationTest : public ::testing::Test {
  68. protected:
  69. SingleEvaluationTest() {
  70. p_ = s_;
  71. a_ = 0;
  72. b_ = 0;
  73. }
  74. static const char* const s_;
  75. static const char* p_;
  76. static int a_;
  77. static int b_;
  78. };
  79. const char* const SingleEvaluationTest::s_ = "01234";
  80. const char* SingleEvaluationTest::p_;
  81. int SingleEvaluationTest::a_;
  82. int SingleEvaluationTest::b_;
  83. void DoNothing() {}
  84. void ThrowException() {
  85. throw std::runtime_error("test");
  86. }
  87. void ThrowSystemError() {
  88. throw fmt::SystemError(EDOM, "test");
  89. }
  90. // Tests that when EXPECT_THROW_MSG fails, it evaluates its message argument
  91. // exactly once.
  92. TEST_F(SingleEvaluationTest, FailedEXPECT_THROW_MSG) {
  93. EXPECT_NONFATAL_FAILURE(
  94. EXPECT_THROW_MSG(ThrowException(), std::exception, p_++), "01234");
  95. EXPECT_EQ(s_ + 1, p_);
  96. }
  97. // Tests that when EXPECT_SYSTEM_ERROR fails, it evaluates its message argument
  98. // exactly once.
  99. TEST_F(SingleEvaluationTest, FailedEXPECT_SYSTEM_ERROR) {
  100. EXPECT_NONFATAL_FAILURE(
  101. EXPECT_SYSTEM_ERROR(ThrowSystemError(), EDOM, p_++), "01234");
  102. EXPECT_EQ(s_ + 1, p_);
  103. }
  104. // Tests that when EXPECT_WRITE fails, it evaluates its message argument
  105. // exactly once.
  106. TEST_F(SingleEvaluationTest, FailedEXPECT_WRITE) {
  107. EXPECT_NONFATAL_FAILURE(
  108. EXPECT_WRITE(stdout, std::printf("test"), p_++), "01234");
  109. EXPECT_EQ(s_ + 1, p_);
  110. }
  111. // Tests that assertion arguments are evaluated exactly once.
  112. TEST_F(SingleEvaluationTest, ExceptionTests) {
  113. // successful EXPECT_THROW_MSG
  114. EXPECT_THROW_MSG({ // NOLINT
  115. a_++;
  116. ThrowException();
  117. }, std::exception, (b_++, "test"));
  118. EXPECT_EQ(1, a_);
  119. EXPECT_EQ(1, b_);
  120. // failed EXPECT_THROW_MSG, throws different type
  121. EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG({ // NOLINT
  122. a_++;
  123. ThrowException();
  124. }, std::logic_error, (b_++, "test")), "throws a different type");
  125. EXPECT_EQ(2, a_);
  126. EXPECT_EQ(2, b_);
  127. // failed EXPECT_THROW_MSG, throws an exception with different message
  128. EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG({ // NOLINT
  129. a_++;
  130. ThrowException();
  131. }, std::exception, (b_++, "other")),
  132. "throws an exception with a different message");
  133. EXPECT_EQ(3, a_);
  134. EXPECT_EQ(3, b_);
  135. // failed EXPECT_THROW_MSG, throws nothing
  136. EXPECT_NONFATAL_FAILURE(
  137. EXPECT_THROW_MSG(a_++, std::exception, (b_++, "test")), "throws nothing");
  138. EXPECT_EQ(4, a_);
  139. EXPECT_EQ(4, b_);
  140. }
  141. TEST_F(SingleEvaluationTest, SystemErrorTests) {
  142. // successful EXPECT_SYSTEM_ERROR
  143. EXPECT_SYSTEM_ERROR({ // NOLINT
  144. a_++;
  145. ThrowSystemError();
  146. }, EDOM, (b_++, "test"));
  147. EXPECT_EQ(1, a_);
  148. EXPECT_EQ(1, b_);
  149. // failed EXPECT_SYSTEM_ERROR, throws different type
  150. EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR({ // NOLINT
  151. a_++;
  152. ThrowException();
  153. }, EDOM, (b_++, "test")), "throws a different type");
  154. EXPECT_EQ(2, a_);
  155. EXPECT_EQ(2, b_);
  156. // failed EXPECT_SYSTEM_ERROR, throws an exception with different message
  157. EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR({ // NOLINT
  158. a_++;
  159. ThrowSystemError();
  160. }, EDOM, (b_++, "other")),
  161. "throws an exception with a different message");
  162. EXPECT_EQ(3, a_);
  163. EXPECT_EQ(3, b_);
  164. // failed EXPECT_SYSTEM_ERROR, throws nothing
  165. EXPECT_NONFATAL_FAILURE(
  166. EXPECT_SYSTEM_ERROR(a_++, EDOM, (b_++, "test")), "throws nothing");
  167. EXPECT_EQ(4, a_);
  168. EXPECT_EQ(4, b_);
  169. }
  170. // Tests that assertion arguments are evaluated exactly once.
  171. TEST_F(SingleEvaluationTest, WriteTests) {
  172. // successful EXPECT_WRITE
  173. EXPECT_WRITE(stdout, { // NOLINT
  174. a_++;
  175. std::printf("test");
  176. }, (b_++, "test"));
  177. EXPECT_EQ(1, a_);
  178. EXPECT_EQ(1, b_);
  179. // failed EXPECT_WRITE
  180. EXPECT_NONFATAL_FAILURE(EXPECT_WRITE(stdout, { // NOLINT
  181. a_++;
  182. std::printf("test");
  183. }, (b_++, "other")), "Actual: test");
  184. EXPECT_EQ(2, a_);
  185. EXPECT_EQ(2, b_);
  186. }
  187. // Tests that the compiler will not complain about unreachable code in the
  188. // EXPECT_THROW_MSG macro.
  189. TEST(ExpectThrowTest, DoesNotGenerateUnreachableCodeWarning) {
  190. int n = 0;
  191. using std::runtime_error;
  192. EXPECT_THROW_MSG(throw runtime_error(""), runtime_error, "");
  193. EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG(n++, runtime_error, ""), "");
  194. EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG(throw 1, runtime_error, ""), "");
  195. EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG(
  196. throw runtime_error("a"), runtime_error, "b"), "");
  197. }
  198. // Tests that the compiler will not complain about unreachable code in the
  199. // EXPECT_SYSTEM_ERROR macro.
  200. TEST(ExpectSystemErrorTest, DoesNotGenerateUnreachableCodeWarning) {
  201. int n = 0;
  202. EXPECT_SYSTEM_ERROR(throw fmt::SystemError(EDOM, "test"), EDOM, "test");
  203. EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(n++, EDOM, ""), "");
  204. EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(throw 1, EDOM, ""), "");
  205. EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(
  206. throw fmt::SystemError(EDOM, "aaa"), EDOM, "bbb"), "");
  207. }
  208. TEST(AssertionSyntaxTest, ExceptionAssertionBehavesLikeSingleStatement) {
  209. if (::testing::internal::AlwaysFalse())
  210. EXPECT_THROW_MSG(DoNothing(), std::exception, "");
  211. if (::testing::internal::AlwaysTrue())
  212. EXPECT_THROW_MSG(ThrowException(), std::exception, "test");
  213. else
  214. DoNothing();
  215. }
  216. TEST(AssertionSyntaxTest, SystemErrorAssertionBehavesLikeSingleStatement) {
  217. if (::testing::internal::AlwaysFalse())
  218. EXPECT_SYSTEM_ERROR(DoNothing(), EDOM, "");
  219. if (::testing::internal::AlwaysTrue())
  220. EXPECT_SYSTEM_ERROR(ThrowSystemError(), EDOM, "test");
  221. else
  222. DoNothing();
  223. }
  224. TEST(AssertionSyntaxTest, WriteAssertionBehavesLikeSingleStatement) {
  225. if (::testing::internal::AlwaysFalse())
  226. EXPECT_WRITE(stdout, std::printf("x"), "x");
  227. if (::testing::internal::AlwaysTrue())
  228. EXPECT_WRITE(stdout, std::printf("x"), "x");
  229. else
  230. DoNothing();
  231. }
  232. // Tests EXPECT_THROW_MSG.
  233. TEST(ExpectTest, EXPECT_THROW_MSG) {
  234. EXPECT_THROW_MSG(ThrowException(), std::exception, "test");
  235. EXPECT_NONFATAL_FAILURE(
  236. EXPECT_THROW_MSG(ThrowException(), std::logic_error, "test"),
  237. "Expected: ThrowException() throws an exception of "
  238. "type std::logic_error.\n Actual: it throws a different type.");
  239. EXPECT_NONFATAL_FAILURE(
  240. EXPECT_THROW_MSG(DoNothing(), std::exception, "test"),
  241. "Expected: DoNothing() throws an exception of type std::exception.\n"
  242. " Actual: it throws nothing.");
  243. EXPECT_NONFATAL_FAILURE(
  244. EXPECT_THROW_MSG(ThrowException(), std::exception, "other"),
  245. "ThrowException() throws an exception with a different message.\n"
  246. "Expected: other\n"
  247. " Actual: test");
  248. }
  249. // Tests EXPECT_SYSTEM_ERROR.
  250. TEST(ExpectTest, EXPECT_SYSTEM_ERROR) {
  251. EXPECT_SYSTEM_ERROR(ThrowSystemError(), EDOM, "test");
  252. EXPECT_NONFATAL_FAILURE(
  253. EXPECT_SYSTEM_ERROR(ThrowException(), EDOM, "test"),
  254. "Expected: ThrowException() throws an exception of "
  255. "type fmt::SystemError.\n Actual: it throws a different type.");
  256. EXPECT_NONFATAL_FAILURE(
  257. EXPECT_SYSTEM_ERROR(DoNothing(), EDOM, "test"),
  258. "Expected: DoNothing() throws an exception of type fmt::SystemError.\n"
  259. " Actual: it throws nothing.");
  260. EXPECT_NONFATAL_FAILURE(
  261. EXPECT_SYSTEM_ERROR(ThrowSystemError(), EDOM, "other"),
  262. fmt::format(
  263. "ThrowSystemError() throws an exception with a different message.\n"
  264. "Expected: {}\n"
  265. " Actual: {}",
  266. FormatSystemErrorMessage(EDOM, "other"),
  267. FormatSystemErrorMessage(EDOM, "test")));
  268. }
  269. // Tests EXPECT_WRITE.
  270. TEST(ExpectTest, EXPECT_WRITE) {
  271. EXPECT_WRITE(stdout, DoNothing(), "");
  272. EXPECT_WRITE(stdout, std::printf("test"), "test");
  273. EXPECT_WRITE(stderr, std::fprintf(stderr, "test"), "test");
  274. EXPECT_NONFATAL_FAILURE(
  275. EXPECT_WRITE(stdout, std::printf("that"), "this"),
  276. "Expected: this\n"
  277. " Actual: that");
  278. }
  279. TEST(StreamingAssertionsTest, EXPECT_THROW_MSG) {
  280. EXPECT_THROW_MSG(ThrowException(), std::exception, "test")
  281. << "unexpected failure";
  282. EXPECT_NONFATAL_FAILURE(
  283. EXPECT_THROW_MSG(ThrowException(), std::exception, "other")
  284. << "expected failure", "expected failure");
  285. }
  286. TEST(StreamingAssertionsTest, EXPECT_SYSTEM_ERROR) {
  287. EXPECT_SYSTEM_ERROR(ThrowSystemError(), EDOM, "test")
  288. << "unexpected failure";
  289. EXPECT_NONFATAL_FAILURE(
  290. EXPECT_SYSTEM_ERROR(ThrowSystemError(), EDOM, "other")
  291. << "expected failure", "expected failure");
  292. }
  293. TEST(StreamingAssertionsTest, EXPECT_WRITE) {
  294. EXPECT_WRITE(stdout, std::printf("test"), "test")
  295. << "unexpected failure";
  296. EXPECT_NONFATAL_FAILURE(
  297. EXPECT_WRITE(stdout, std::printf("test"), "other")
  298. << "expected failure", "expected failure");
  299. }
  300. TEST(UtilTest, FormatSystemErrorMessage) {
  301. fmt::Writer out;
  302. fmt::internal::FormatSystemErrorMessage(out, EDOM, "test message");
  303. EXPECT_EQ(out.str(), FormatSystemErrorMessage(EDOM, "test message"));
  304. }
  305. #if FMT_USE_FILE_DESCRIPTORS
  306. using fmt::BufferedFile;
  307. using fmt::ErrorCode;
  308. using fmt::File;
  309. // Checks if the file is open by reading one character from it.
  310. bool IsOpen(int fd) {
  311. char buffer;
  312. return FMT_POSIX(read(fd, &buffer, 1)) == 1;
  313. }
  314. bool IsClosed(int fd) {
  315. char buffer;
  316. std::streamsize result = 0;
  317. SUPPRESS_ASSERT(result = FMT_POSIX(read(fd, &buffer, 1)));
  318. return result == -1 && errno == EBADF;
  319. }
  320. // Attempts to read count characters from a file.
  321. std::string Read(File &f, std::size_t count) {
  322. std::string buffer(count, '\0');
  323. std::streamsize n = 0;
  324. std::size_t offset = 0;
  325. do {
  326. n = f.read(&buffer[offset], count - offset);
  327. // We can't read more than size_t bytes since count has type size_t.
  328. offset += static_cast<std::size_t>(n);
  329. } while (offset < count && n != 0);
  330. buffer.resize(offset);
  331. return buffer;
  332. }
  333. // Attempts to write a string to a file.
  334. void Write(File &f, fmt::StringRef s) {
  335. std::size_t num_chars_left = s.size();
  336. const char *ptr = s.c_str();
  337. do {
  338. std::streamsize count = f.write(ptr, num_chars_left);
  339. ptr += count;
  340. // We can't write more than size_t bytes since num_chars_left
  341. // has type size_t.
  342. num_chars_left -= static_cast<std::size_t>(count);
  343. } while (num_chars_left != 0);
  344. }
  345. #define EXPECT_READ(file, expected_content) \
  346. EXPECT_EQ(expected_content, Read(file, std::strlen(expected_content)))
  347. TEST(ErrorCodeTest, Ctor) {
  348. EXPECT_EQ(0, ErrorCode().get());
  349. EXPECT_EQ(42, ErrorCode(42).get());
  350. }
  351. const char FILE_CONTENT[] = "Don't panic!";
  352. // Opens a file for reading.
  353. File OpenFile() {
  354. File read_end, write_end;
  355. File::pipe(read_end, write_end);
  356. write_end.write(FILE_CONTENT, sizeof(FILE_CONTENT) - 1);
  357. write_end.close();
  358. return read_end;
  359. }
  360. // Opens a buffered file for reading.
  361. BufferedFile OpenBufferedFile(FILE **fp = 0) {
  362. File read_end, write_end;
  363. File::pipe(read_end, write_end);
  364. write_end.write(FILE_CONTENT, sizeof(FILE_CONTENT) - 1);
  365. write_end.close();
  366. BufferedFile f = read_end.fdopen("r");
  367. if (fp)
  368. *fp = f.get();
  369. return f;
  370. }
  371. TEST(BufferedFileTest, DefaultCtor) {
  372. BufferedFile f;
  373. EXPECT_TRUE(f.get() == 0);
  374. }
  375. TEST(BufferedFileTest, MoveCtor) {
  376. BufferedFile bf = OpenBufferedFile();
  377. FILE *fp = bf.get();
  378. EXPECT_TRUE(fp != 0);
  379. BufferedFile bf2(std::move(bf));
  380. EXPECT_EQ(fp, bf2.get());
  381. EXPECT_TRUE(bf.get() == 0);
  382. }
  383. TEST(BufferedFileTest, MoveAssignment) {
  384. BufferedFile bf = OpenBufferedFile();
  385. FILE *fp = bf.get();
  386. EXPECT_TRUE(fp != 0);
  387. BufferedFile bf2;
  388. bf2 = std::move(bf);
  389. EXPECT_EQ(fp, bf2.get());
  390. EXPECT_TRUE(bf.get() == 0);
  391. }
  392. TEST(BufferedFileTest, MoveAssignmentClosesFile) {
  393. BufferedFile bf = OpenBufferedFile();
  394. BufferedFile bf2 = OpenBufferedFile();
  395. int old_fd = bf2.fileno();
  396. bf2 = std::move(bf);
  397. EXPECT_TRUE(IsClosed(old_fd));
  398. }
  399. TEST(BufferedFileTest, MoveFromTemporaryInCtor) {
  400. FILE *fp = 0;
  401. BufferedFile f(OpenBufferedFile(&fp));
  402. EXPECT_EQ(fp, f.get());
  403. }
  404. TEST(BufferedFileTest, MoveFromTemporaryInAssignment) {
  405. FILE *fp = 0;
  406. BufferedFile f;
  407. f = OpenBufferedFile(&fp);
  408. EXPECT_EQ(fp, f.get());
  409. }
  410. TEST(BufferedFileTest, MoveFromTemporaryInAssignmentClosesFile) {
  411. BufferedFile f = OpenBufferedFile();
  412. int old_fd = f.fileno();
  413. f = OpenBufferedFile();
  414. EXPECT_TRUE(IsClosed(old_fd));
  415. }
  416. TEST(BufferedFileTest, CloseFileInDtor) {
  417. int fd = 0;
  418. {
  419. BufferedFile f = OpenBufferedFile();
  420. fd = f.fileno();
  421. }
  422. EXPECT_TRUE(IsClosed(fd));
  423. }
  424. TEST(BufferedFileTest, CloseErrorInDtor) {
  425. BufferedFile *f = new BufferedFile(OpenBufferedFile());
  426. EXPECT_WRITE(stderr, {
  427. // The close function must be called inside EXPECT_WRITE, otherwise
  428. // the system may recycle closed file descriptor when redirecting the
  429. // output in EXPECT_STDERR and the second close will break output
  430. // redirection.
  431. FMT_POSIX(close(f->fileno()));
  432. SUPPRESS_ASSERT(delete f);
  433. }, FormatSystemErrorMessage(EBADF, "cannot close file") + "\n");
  434. }
  435. TEST(BufferedFileTest, Close) {
  436. BufferedFile f = OpenBufferedFile();
  437. int fd = f.fileno();
  438. f.close();
  439. EXPECT_TRUE(f.get() == 0);
  440. EXPECT_TRUE(IsClosed(fd));
  441. }
  442. TEST(BufferedFileTest, CloseError) {
  443. BufferedFile f = OpenBufferedFile();
  444. FMT_POSIX(close(f.fileno()));
  445. EXPECT_SYSTEM_ERROR_NOASSERT(f.close(), EBADF, "cannot close file");
  446. EXPECT_TRUE(f.get() == 0);
  447. }
  448. TEST(BufferedFileTest, Fileno) {
  449. BufferedFile f;
  450. // fileno on a null FILE pointer either crashes or returns an error.
  451. EXPECT_DEATH({
  452. try {
  453. f.fileno();
  454. } catch (fmt::SystemError) {
  455. std::exit(1);
  456. }
  457. }, "");
  458. f = OpenBufferedFile();
  459. EXPECT_TRUE(f.fileno() != -1);
  460. File copy = File::dup(f.fileno());
  461. EXPECT_READ(copy, FILE_CONTENT);
  462. }
  463. TEST(FileTest, DefaultCtor) {
  464. File f;
  465. EXPECT_EQ(-1, f.descriptor());
  466. }
  467. TEST(FileTest, OpenBufferedFileInCtor) {
  468. FILE *fp = fopen("test-file", "w");
  469. std::fputs(FILE_CONTENT, fp);
  470. std::fclose(fp);
  471. File f("test-file", File::RDONLY);
  472. ASSERT_TRUE(IsOpen(f.descriptor()));
  473. }
  474. TEST(FileTest, OpenBufferedFileError) {
  475. EXPECT_SYSTEM_ERROR(File("nonexistent", File::RDONLY),
  476. ENOENT, "cannot open file nonexistent");
  477. }
  478. TEST(FileTest, MoveCtor) {
  479. File f = OpenFile();
  480. int fd = f.descriptor();
  481. EXPECT_NE(-1, fd);
  482. File f2(std::move(f));
  483. EXPECT_EQ(fd, f2.descriptor());
  484. EXPECT_EQ(-1, f.descriptor());
  485. }
  486. TEST(FileTest, MoveAssignment) {
  487. File f = OpenFile();
  488. int fd = f.descriptor();
  489. EXPECT_NE(-1, fd);
  490. File f2;
  491. f2 = std::move(f);
  492. EXPECT_EQ(fd, f2.descriptor());
  493. EXPECT_EQ(-1, f.descriptor());
  494. }
  495. TEST(FileTest, MoveAssignmentClosesFile) {
  496. File f = OpenFile();
  497. File f2 = OpenFile();
  498. int old_fd = f2.descriptor();
  499. f2 = std::move(f);
  500. EXPECT_TRUE(IsClosed(old_fd));
  501. }
  502. File OpenBufferedFile(int &fd) {
  503. File f = OpenFile();
  504. fd = f.descriptor();
  505. return std::move(f);
  506. }
  507. TEST(FileTest, MoveFromTemporaryInCtor) {
  508. int fd = 0xdeadbeef;
  509. File f(OpenBufferedFile(fd));
  510. EXPECT_EQ(fd, f.descriptor());
  511. }
  512. TEST(FileTest, MoveFromTemporaryInAssignment) {
  513. int fd = 0xdeadbeef;
  514. File f;
  515. f = OpenBufferedFile(fd);
  516. EXPECT_EQ(fd, f.descriptor());
  517. }
  518. TEST(FileTest, MoveFromTemporaryInAssignmentClosesFile) {
  519. int fd = 0xdeadbeef;
  520. File f = OpenFile();
  521. int old_fd = f.descriptor();
  522. f = OpenBufferedFile(fd);
  523. EXPECT_TRUE(IsClosed(old_fd));
  524. }
  525. TEST(FileTest, CloseFileInDtor) {
  526. int fd = 0;
  527. {
  528. File f = OpenFile();
  529. fd = f.descriptor();
  530. }
  531. EXPECT_TRUE(IsClosed(fd));
  532. }
  533. TEST(FileTest, CloseErrorInDtor) {
  534. File *f = new File(OpenFile());
  535. EXPECT_WRITE(stderr, {
  536. // The close function must be called inside EXPECT_WRITE, otherwise
  537. // the system may recycle closed file descriptor when redirecting the
  538. // output in EXPECT_STDERR and the second close will break output
  539. // redirection.
  540. FMT_POSIX(close(f->descriptor()));
  541. SUPPRESS_ASSERT(delete f);
  542. }, FormatSystemErrorMessage(EBADF, "cannot close file") + "\n");
  543. }
  544. TEST(FileTest, Close) {
  545. File f = OpenFile();
  546. int fd = f.descriptor();
  547. f.close();
  548. EXPECT_EQ(-1, f.descriptor());
  549. EXPECT_TRUE(IsClosed(fd));
  550. }
  551. TEST(FileTest, CloseError) {
  552. File f = OpenFile();
  553. FMT_POSIX(close(f.descriptor()));
  554. EXPECT_SYSTEM_ERROR_NOASSERT(f.close(), EBADF, "cannot close file");
  555. EXPECT_EQ(-1, f.descriptor());
  556. }
  557. TEST(FileTest, Read) {
  558. File f = OpenFile();
  559. EXPECT_READ(f, FILE_CONTENT);
  560. }
  561. TEST(FileTest, ReadError) {
  562. File read_end, write_end;
  563. File::pipe(read_end, write_end);
  564. char buf;
  565. // We intentionally read from write_end to cause error.
  566. EXPECT_SYSTEM_ERROR(write_end.read(&buf, 1), EBADF, "cannot read from file");
  567. }
  568. TEST(FileTest, Write) {
  569. File read_end, write_end;
  570. File::pipe(read_end, write_end);
  571. Write(write_end, "test");
  572. write_end.close();
  573. EXPECT_READ(read_end, "test");
  574. }
  575. TEST(FileTest, WriteError) {
  576. File read_end, write_end;
  577. File::pipe(read_end, write_end);
  578. // We intentionally write to read_end to cause error.
  579. EXPECT_SYSTEM_ERROR(read_end.write(" ", 1), EBADF, "cannot write to file");
  580. }
  581. TEST(FileTest, Dup) {
  582. File f = OpenFile();
  583. File copy = File::dup(f.descriptor());
  584. EXPECT_NE(f.descriptor(), copy.descriptor());
  585. EXPECT_EQ(FILE_CONTENT, Read(copy, sizeof(FILE_CONTENT) - 1));
  586. }
  587. TEST(FileTest, DupError) {
  588. EXPECT_SYSTEM_ERROR_NOASSERT(File::dup(-1),
  589. EBADF, "cannot duplicate file descriptor -1");
  590. }
  591. TEST(FileTest, Dup2) {
  592. File f = OpenFile();
  593. File copy = OpenFile();
  594. f.dup2(copy.descriptor());
  595. EXPECT_NE(f.descriptor(), copy.descriptor());
  596. EXPECT_READ(copy, FILE_CONTENT);
  597. }
  598. TEST(FileTest, Dup2Error) {
  599. File f = OpenFile();
  600. EXPECT_SYSTEM_ERROR_NOASSERT(f.dup2(-1), EBADF,
  601. fmt::format("cannot duplicate file descriptor {} to -1", f.descriptor()));
  602. }
  603. TEST(FileTest, Dup2NoExcept) {
  604. File f = OpenFile();
  605. File copy = OpenFile();
  606. ErrorCode ec;
  607. f.dup2(copy.descriptor(), ec);
  608. EXPECT_EQ(0, ec.get());
  609. EXPECT_NE(f.descriptor(), copy.descriptor());
  610. EXPECT_READ(copy, FILE_CONTENT);
  611. }
  612. TEST(FileTest, Dup2NoExceptError) {
  613. File f = OpenFile();
  614. ErrorCode ec;
  615. SUPPRESS_ASSERT(f.dup2(-1, ec));
  616. EXPECT_EQ(EBADF, ec.get());
  617. }
  618. TEST(FileTest, Pipe) {
  619. File read_end, write_end;
  620. File::pipe(read_end, write_end);
  621. EXPECT_NE(-1, read_end.descriptor());
  622. EXPECT_NE(-1, write_end.descriptor());
  623. Write(write_end, "test");
  624. EXPECT_READ(read_end, "test");
  625. }
  626. TEST(FileTest, Fdopen) {
  627. File read_end, write_end;
  628. File::pipe(read_end, write_end);
  629. int read_fd = read_end.descriptor();
  630. EXPECT_EQ(read_fd, FMT_POSIX(fileno(read_end.fdopen("r").get())));
  631. }
  632. TEST(FileTest, FdopenError) {
  633. File f;
  634. EXPECT_SYSTEM_ERROR_NOASSERT(
  635. f.fdopen("r"), EBADF, "cannot associate stream with file descriptor");
  636. }
  637. TEST(OutputRedirectTest, ScopedRedirect) {
  638. File read_end, write_end;
  639. File::pipe(read_end, write_end);
  640. {
  641. BufferedFile file(write_end.fdopen("w"));
  642. std::fprintf(file.get(), "[[[");
  643. {
  644. OutputRedirect redir(file.get());
  645. std::fprintf(file.get(), "censored");
  646. }
  647. std::fprintf(file.get(), "]]]");
  648. }
  649. EXPECT_READ(read_end, "[[[]]]");
  650. }
  651. // Test that OutputRedirect handles errors in flush correctly.
  652. TEST(OutputRedirectTest, FlushErrorInCtor) {
  653. File read_end, write_end;
  654. File::pipe(read_end, write_end);
  655. int write_fd = write_end.descriptor();
  656. File write_copy = write_end.dup(write_fd);
  657. BufferedFile f = write_end.fdopen("w");
  658. // Put a character in a file buffer.
  659. EXPECT_EQ('x', fputc('x', f.get()));
  660. FMT_POSIX(close(write_fd));
  661. OutputRedirect *redir = 0;
  662. EXPECT_SYSTEM_ERROR_NOASSERT(redir = new OutputRedirect(f.get()),
  663. EBADF, "cannot flush stream");
  664. delete redir;
  665. write_copy.dup2(write_fd); // "undo" close or dtor will fail
  666. }
  667. TEST(OutputRedirectTest, DupErrorInCtor) {
  668. BufferedFile f = OpenBufferedFile();
  669. int fd = f.fileno();
  670. File copy = File::dup(fd);
  671. FMT_POSIX(close(fd));
  672. OutputRedirect *redir = 0;
  673. EXPECT_SYSTEM_ERROR_NOASSERT(redir = new OutputRedirect(f.get()),
  674. EBADF, fmt::format("cannot duplicate file descriptor {}", fd));
  675. copy.dup2(fd); // "undo" close or dtor will fail
  676. delete redir;
  677. }
  678. TEST(OutputRedirectTest, RestoreAndRead) {
  679. File read_end, write_end;
  680. File::pipe(read_end, write_end);
  681. BufferedFile file(write_end.fdopen("w"));
  682. std::fprintf(file.get(), "[[[");
  683. OutputRedirect redir(file.get());
  684. std::fprintf(file.get(), "censored");
  685. EXPECT_EQ("censored", redir.RestoreAndRead());
  686. EXPECT_EQ("", redir.RestoreAndRead());
  687. std::fprintf(file.get(), "]]]");
  688. file = BufferedFile();
  689. EXPECT_READ(read_end, "[[[]]]");
  690. }
  691. // Test that OutputRedirect handles errors in flush correctly.
  692. TEST(OutputRedirectTest, FlushErrorInRestoreAndRead) {
  693. File read_end, write_end;
  694. File::pipe(read_end, write_end);
  695. int write_fd = write_end.descriptor();
  696. File write_copy = write_end.dup(write_fd);
  697. BufferedFile f = write_end.fdopen("w");
  698. OutputRedirect redir(f.get());
  699. // Put a character in a file buffer.
  700. EXPECT_EQ('x', fputc('x', f.get()));
  701. FMT_POSIX(close(write_fd));
  702. EXPECT_SYSTEM_ERROR_NOASSERT(redir.RestoreAndRead(),
  703. EBADF, "cannot flush stream");
  704. write_copy.dup2(write_fd); // "undo" close or dtor will fail
  705. }
  706. TEST(OutputRedirectTest, ErrorInDtor) {
  707. File read_end, write_end;
  708. File::pipe(read_end, write_end);
  709. int write_fd = write_end.descriptor();
  710. File write_copy = write_end.dup(write_fd);
  711. BufferedFile f = write_end.fdopen("w");
  712. OutputRedirect *redir = new OutputRedirect(f.get());
  713. // Put a character in a file buffer.
  714. EXPECT_EQ('x', fputc('x', f.get()));
  715. EXPECT_WRITE(stderr, {
  716. // The close function must be called inside EXPECT_WRITE, otherwise
  717. // the system may recycle closed file descriptor when redirecting the
  718. // output in EXPECT_STDERR and the second close will break output
  719. // redirection.
  720. FMT_POSIX(close(write_fd));
  721. SUPPRESS_ASSERT(delete redir);
  722. }, FormatSystemErrorMessage(EBADF, "cannot flush stream"));
  723. write_copy.dup2(write_fd); // "undo" close or dtor of BufferedFile will fail
  724. }
  725. #endif // FMT_USE_FILE_DESCRIPTORS
  726. } // namespace