proxygen
FileHandlerFactoryTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
18 
19 #include <folly/Exception.h>
26 #include <folly/test/TestUtils.h>
27 
28 using namespace folly;
30 using std::make_pair;
31 
33  const LogWriter* writer,
34  const char* expectedPath,
35  size_t expectedMaxBufferSize) {
36  auto asyncWriter = dynamic_cast<const AsyncFileWriter*>(writer);
37  ASSERT_TRUE(asyncWriter)
38  << "handler factory should have created an AsyncFileWriter";
39  EXPECT_EQ(expectedMaxBufferSize, asyncWriter->getMaxBufferSize());
40 
41  // Make sure this refers to the expected output file
42  struct stat expectedStatInfo;
43  checkUnixError(stat(expectedPath, &expectedStatInfo), "stat failed");
44  struct stat actualStatInfo;
46  fstat(asyncWriter->getFile().fd(), &actualStatInfo), "fstat failed");
47  EXPECT_EQ(expectedStatInfo.st_dev, actualStatInfo.st_dev);
48  EXPECT_EQ(expectedStatInfo.st_ino, actualStatInfo.st_ino);
49 }
50 
52  const LogWriter* writer,
53  int expectedFD,
54  size_t expectedMaxBufferSize) {
55  auto asyncWriter = dynamic_cast<const AsyncFileWriter*>(writer);
56  ASSERT_TRUE(asyncWriter)
57  << "handler factory should have created an AsyncFileWriter";
58  EXPECT_EQ(expectedMaxBufferSize, asyncWriter->getMaxBufferSize());
59  EXPECT_EQ(expectedFD, asyncWriter->getFile().fd());
60 }
61 
63  FileHandlerFactory factory;
64 
65  TemporaryFile tmpFile{"logging_test"};
66  auto options = LogHandlerFactory::Options{
67  make_pair("path", tmpFile.path().string()),
68  };
69  auto handler = factory.createHandler(options);
70 
71  auto stdHandler = std::dynamic_pointer_cast<StandardLogHandler>(handler);
72  ASSERT_TRUE(stdHandler);
73 
74  auto formatter =
75  std::dynamic_pointer_cast<GlogStyleFormatter>(stdHandler->getFormatter());
76  EXPECT_TRUE(formatter)
77  << "handler factory should have created a GlogStyleFormatter";
78 
80  stdHandler->getWriter().get(),
81  tmpFile.path().string().c_str(),
83 }
84 
85 TEST(StreamHandlerFactory, stderrStream) {
86  StreamHandlerFactory factory;
87 
88  TemporaryFile tmpFile{"logging_test"};
89  auto options = StreamHandlerFactory::Options{
90  make_pair("stream", "stderr"),
91  };
92  auto handler = factory.createHandler(options);
93 
94  auto stdHandler = std::dynamic_pointer_cast<StandardLogHandler>(handler);
95  ASSERT_TRUE(stdHandler);
96 
97  auto formatter =
98  std::dynamic_pointer_cast<GlogStyleFormatter>(stdHandler->getFormatter());
99  EXPECT_TRUE(formatter)
100  << "handler factory should have created a GlogStyleFormatter";
101 
103  stdHandler->getWriter().get(),
104  STDERR_FILENO,
106 }
107 
108 TEST(StreamHandlerFactory, stdoutWithMaxBuffer) {
109  StreamHandlerFactory factory;
110 
111  TemporaryFile tmpFile{"logging_test"};
112  auto options = StreamHandlerFactory::Options{
113  make_pair("stream", "stdout"),
114  make_pair("max_buffer_size", "4096"),
115  };
116  auto handler = factory.createHandler(options);
117 
118  auto stdHandler = std::dynamic_pointer_cast<StandardLogHandler>(handler);
119  ASSERT_TRUE(stdHandler);
120 
121  auto formatter =
122  std::dynamic_pointer_cast<GlogStyleFormatter>(stdHandler->getFormatter());
123  EXPECT_TRUE(formatter)
124  << "handler factory should have created a GlogStyleFormatter";
125 
126  checkAsyncWriter(stdHandler->getWriter().get(), STDOUT_FILENO, 4096);
127 }
128 
129 TEST(FileHandlerFactory, pathWithMaxBufferSize) {
130  FileHandlerFactory factory;
131 
132  TemporaryFile tmpFile{"logging_test"};
133  auto options = LogHandlerFactory::Options{
134  make_pair("path", tmpFile.path().string()),
135  make_pair("max_buffer_size", "4096000"),
136  };
137  auto handler = factory.createHandler(options);
138 
139  auto stdHandler = std::dynamic_pointer_cast<StandardLogHandler>(handler);
140  ASSERT_TRUE(stdHandler);
141 
142  auto formatter =
143  std::dynamic_pointer_cast<GlogStyleFormatter>(stdHandler->getFormatter());
144  EXPECT_TRUE(formatter)
145  << "handler factory should have created a GlogStyleFormatter";
146 
148  stdHandler->getWriter().get(), tmpFile.path().string().c_str(), 4096000);
149 }
150 
151 TEST(StreamHandlerFactory, nonAsyncStderr) {
152  StreamHandlerFactory factory;
153 
154  TemporaryFile tmpFile{"logging_test"};
155  auto options = LogHandlerFactory::Options{
156  make_pair("stream", "stderr"),
157  make_pair("async", "no"),
158  };
159  auto handler = factory.createHandler(options);
160 
161  auto stdHandler = std::dynamic_pointer_cast<StandardLogHandler>(handler);
162  ASSERT_TRUE(stdHandler);
163 
164  auto formatter =
165  std::dynamic_pointer_cast<GlogStyleFormatter>(stdHandler->getFormatter());
166  EXPECT_TRUE(formatter)
167  << "handler factory should have created a GlogStyleFormatter";
168 
169  auto writer =
170  std::dynamic_pointer_cast<ImmediateFileWriter>(stdHandler->getWriter());
171  ASSERT_TRUE(writer);
172  EXPECT_EQ(STDERR_FILENO, writer->getFile().fd());
173 }
174 
176  FileHandlerFactory factory;
177  TemporaryFile tmpFile{"logging_test"};
178  using Options = LogHandlerFactory::Options;
179 
180  {
181  auto options = Options{};
183  factory.createHandler(options),
184  std::invalid_argument,
185  "no path specified for file handler");
186  }
187 
188  {
189  auto options = Options{
190  {"path", tmpFile.path().string()},
191  {"stream", "stderr"},
192  };
194  factory.createHandler(options),
195  std::invalid_argument,
196  "unknown option \"stream\"");
197  }
198 
199  {
200  auto options = Options{
201  {"stream", "nonstdout"},
202  };
204  factory.createHandler(options),
205  std::invalid_argument,
206  "unknown option \"stream\"");
207  }
208 
209  {
210  auto options = Options{
211  {"path", tmpFile.path().string()},
212  {"async", "xyz"},
213  };
215  factory.createHandler(options),
216  std::invalid_argument,
217  "^error processing option \"async\": Invalid value for bool: \"xyz\"$");
218  }
219 
220  {
221  auto options = Options{
222  {"path", tmpFile.path().string()},
223  {"async", "false"},
224  {"max_buffer_size", "1234"},
225  };
227  factory.createHandler(options),
228  std::invalid_argument,
229  "the \"max_buffer_size\" option is only valid for async file handlers");
230  }
231 
232  {
233  auto options = Options{
234  {"path", tmpFile.path().string()},
235  {"max_buffer_size", "hello"},
236  };
238  factory.createHandler(options),
239  std::invalid_argument,
240  "^error processing option \"max_buffer_size\": "
241  "Non-digit character found: \"hello\"$");
242  }
243 
244  {
245  auto options = Options{
246  {"path", tmpFile.path().string()},
247  {"max_buffer_size", "0"},
248  };
250  factory.createHandler(options),
251  std::invalid_argument,
252  "^error processing option \"max_buffer_size\": "
253  "must be a positive integer$");
254  }
255 
256  {
257  auto options = Options{
258  {"path", tmpFile.path().string()},
259  {"foo", "bar"},
260  };
262  factory.createHandler(options),
263  std::invalid_argument,
264  "^unknown option \"foo\"$");
265  }
266 }
267 
269  StreamHandlerFactory factory;
270  using Options = LogHandlerFactory::Options;
271 
272  {
273  auto options = Options{};
275  factory.createHandler(options),
276  std::invalid_argument,
277  "no stream name specified for stream handler");
278  }
279 
280  {
281  auto options = Options{
282  {"path", "/tmp/log.txt"},
283  {"stream", "stderr"},
284  };
286  factory.createHandler(options),
287  std::invalid_argument,
288  "unknown option \"path\"");
289  }
290 
291  {
292  auto options = Options{
293  {"stream", "nonstdout"},
294  };
296  factory.createHandler(options),
297  std::invalid_argument,
298  "unknown stream \"nonstdout\": expected one of stdout or stderr");
299  }
300 
301  {
302  auto options = Options{
303  {"stream", "stderr"},
304  {"async", "xyz"},
305  };
307  factory.createHandler(options),
308  std::invalid_argument,
309  "^error processing option \"async\": Invalid value for bool: \"xyz\"$");
310  }
311 
312  {
313  auto options = Options{
314  {"stream", "stderr"},
315  {"async", "false"},
316  {"max_buffer_size", "1234"},
317  };
319  factory.createHandler(options),
320  std::invalid_argument,
321  "^the \"max_buffer_size\" option is only valid for "
322  "async file handlers$");
323  }
324 
325  {
326  auto options = Options{
327  {"stream", "stderr"},
328  {"max_buffer_size", "hello"},
329  };
331  factory.createHandler(options),
332  std::invalid_argument,
333  "^error processing option \"max_buffer_size\": "
334  "Non-digit character found: \"hello\"$");
335  }
336 
337  {
338  auto options = Options{
339  {"stream", "stderr"},
340  {"max_buffer_size", "0"},
341  };
343  factory.createHandler(options),
344  std::invalid_argument,
345  "^error processing option \"max_buffer_size\": "
346  "must be a positive integer$");
347  }
348 
349  {
350  auto options = Options{
351  make_pair("stream", "stderr"),
352  make_pair("foo", "bar"),
353  };
355  factory.createHandler(options),
356  std::invalid_argument,
357  "unknown option \"foo\"");
358  }
359 }
#define EXPECT_THROW_RE(statement, exceptionType, pattern)
Definition: TestUtils.h:119
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
std::shared_ptr< LogHandler > createHandler(const Options &options) override
void handler(int, siginfo_t *, void *)
static constexpr size_t kDefaultMaxBufferSize
std::shared_ptr< LogHandler > createHandler(const Options &options) override
void checkUnixError(ssize_t ret, Args &&...args)
Definition: Exception.h:101
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
void checkAsyncWriter(const LogWriter *writer, const char *expectedPath, size_t expectedMaxBufferSize)
std::unordered_map< std::string, std::string > Options
#define ASSERT_TRUE(condition)
Definition: gtest.h:1865
TEST(SequencedExecutor, CPUThreadPoolExecutor)