// 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 #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 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