1// Copyright (c) 2013, Google Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8//     * Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10//     * Redistributions in binary form must reproduce the above
11// copyright notice, this list of conditions and the following disclaimer
12// in the documentation and/or other materials provided with the
13// distribution.
14//     * Neither the name of Google Inc. nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30// Utility class for creating a temporary file for unit tests
31// that is deleted in the destructor.
32
33#ifndef GOOGLE_BREAKPAD_COMMON_LINUX_TESTS_AUTO_TESTFILE
34#define GOOGLE_BREAKPAD_COMMON_LINUX_TESTS_AUTO_TESTFILE
35
36#include <unistd.h>
37#include <sys/types.h>
38
39#include <string>
40
41#include "breakpad_googletest_includes.h"
42#include "common/linux/eintr_wrapper.h"
43#include "common/tests/auto_tempdir.h"
44
45namespace google_breakpad {
46
47class AutoTestFile {
48 public:
49  // Create a new empty test file.
50  // test_prefix: (input) test-specific prefix, can't be NULL.
51  explicit AutoTestFile(const char* test_prefix) {
52    Init(test_prefix);
53  }
54
55  // Create a new test file, and fill it with initial data from a C string.
56  // The terminating zero is not written.
57  // test_prefix: (input) test-specific prefix, can't be NULL.
58  // text: (input) initial content.
59  AutoTestFile(const char* test_prefix, const char* text) {
60    Init(test_prefix);
61    if (fd_ >= 0)
62      WriteText(text, static_cast<size_t>(strlen(text)));
63  }
64
65  AutoTestFile(const char* test_prefix, const char* text, size_t text_len) {
66    Init(test_prefix);
67    if (fd_ >= 0)
68      WriteText(text, text_len);
69  }
70
71  // Destroy test file on scope exit.
72  ~AutoTestFile() {
73    if (fd_ >= 0) {
74      close(fd_);
75      fd_ = -1;
76    }
77  }
78
79  // Returns true iff the test file could be created properly.
80  // Useful in tests inside EXPECT_TRUE(file.IsOk());
81  bool IsOk() {
82    return fd_ >= 0;
83  }
84
85  // Returns the Posix file descriptor for the test file, or -1
86  // If IsOk() returns false. Note: on Windows, this always returns -1.
87  int GetFd() {
88    return fd_;
89  }
90
91 private:
92  void Init(const char* test_prefix) {
93    fd_ = -1;
94    char path_templ[PATH_MAX];
95    int ret = snprintf(path_templ, sizeof(path_templ),
96                       TEMPDIR "/%s-unittest.XXXXXX",
97                       test_prefix);
98    if (ret >= static_cast<int>(sizeof(path_templ)))
99      return;
100
101    fd_ = mkstemp(path_templ);
102    if (fd_ < 0)
103      return;
104
105    unlink(path_templ);
106  }
107
108  void WriteText(const char* text, size_t text_len) {
109    ssize_t r = HANDLE_EINTR(write(fd_, text, text_len));
110    if (r != static_cast<ssize_t>(text_len)) {
111      close(fd_);
112      fd_ = -1;
113      return;
114    }
115
116    lseek(fd_, 0, SEEK_SET);
117  }
118
119  int fd_;
120};
121
122}  // namespace google_breakpad
123
124#endif  // GOOGLE_BREAKPAD_COMMON_LINUX_TESTS_AUTO_TESTFILE
125