| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <signal.h> |
| |
| #include "flutter/fml/build_config.h" |
| #include "flutter/fml/log_settings.h" |
| #include "flutter/fml/logging.h" |
| #include "fml/log_level.h" |
| #include "gtest/gtest.h" |
| |
| namespace fml { |
| namespace testing { |
| |
| static_assert(fml::kLogFatal == fml::kLogNumSeverities - 1); |
| static_assert(fml::kLogImportant < fml::kLogFatal); |
| static_assert(fml::kLogImportant > fml::kLogError); |
| |
| #ifndef OS_FUCHSIA |
| class MakeSureFmlLogDoesNotSegfaultWhenStaticallyCalled { |
| public: |
| MakeSureFmlLogDoesNotSegfaultWhenStaticallyCalled() { |
| SegfaultCatcher catcher; |
| // If this line causes a segfault, FML is using a method of logging that is |
| // not safe from static initialization on your platform. |
| FML_LOG(INFO) |
| << "This log exists to verify that static logging from FML works."; |
| } |
| |
| private: |
| struct SegfaultCatcher { |
| typedef void (*sighandler_t)(int); |
| |
| SegfaultCatcher() { |
| handler = ::signal(SIGSEGV, SegfaultHandler); |
| FML_CHECK(handler != SIG_ERR); |
| } |
| |
| ~SegfaultCatcher() { FML_CHECK(::signal(SIGSEGV, handler) != SIG_ERR); } |
| |
| static void SegfaultHandler(int signal) { |
| fprintf(stderr, |
| "FML failed to handle logging from static initialization.\n"); |
| exit(signal); |
| } |
| |
| sighandler_t handler; |
| }; |
| }; |
| |
| static MakeSureFmlLogDoesNotSegfaultWhenStaticallyCalled fml_log_static_check_; |
| #endif // !defined(OS_FUCHSIA) |
| |
| int UnreachableScopeWithoutReturnDoesNotMakeCompilerMad() { |
| KillProcess(); |
| // return 0; <--- Missing but compiler is fine. |
| } |
| |
| int UnreachableScopeWithMacroWithoutReturnDoesNotMakeCompilerMad() { |
| FML_UNREACHABLE(); |
| // return 0; <--- Missing but compiler is fine. |
| } |
| |
| TEST(LoggingTest, UnreachableKillProcess) { |
| ::testing::FLAGS_gtest_death_test_style = "threadsafe"; |
| ASSERT_DEATH(KillProcess(), ""); |
| } |
| |
| TEST(LoggingTest, UnreachableKillProcessWithMacro) { |
| ::testing::FLAGS_gtest_death_test_style = "threadsafe"; |
| ASSERT_DEATH({ FML_UNREACHABLE(); }, ""); |
| } |
| |
| #ifndef OS_FUCHSIA |
| TEST(LoggingTest, SanityTests) { |
| ::testing::FLAGS_gtest_death_test_style = "threadsafe"; |
| std::vector<std::string> severities = {"INFO", "WARNING", "ERROR", |
| "IMPORTANT"}; |
| |
| for (size_t i = 0; i < severities.size(); i++) { |
| LogCapture capture; |
| { |
| LogMessage log(i, "path/to/file.cc", 4, nullptr); |
| log.stream() << "Hello!"; |
| } |
| EXPECT_EQ(capture.str(), std::string("[" + severities[i] + |
| ":path/to/file.cc(4)] Hello!\n")); |
| } |
| |
| ASSERT_DEATH( |
| { |
| LogMessage log(kLogFatal, "path/to/file.cc", 5, nullptr); |
| log.stream() << "Goodbye"; |
| }, |
| R"(\[FATAL:path/to/file.cc\(5\)\] Goodbye)"); |
| } |
| #endif // !OS_FUCHSIA |
| |
| } // namespace testing |
| } // namespace fml |