Skip to content

Commit

Permalink
Add minimal test for DeviceAppender.
Browse files Browse the repository at this point in the history
Fix omission: DeviceAppender does not call destructorImpl().
Modernize.
  • Loading branch information
wilx committed Dec 31, 2023
1 parent 5b9440f commit 16d46d7
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 31 deletions.
106 changes: 78 additions & 28 deletions include/log4cplus/boost/deviceappender.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,11 @@
#pragma once
#endif

#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/not.hpp>
#include <memory>
#include <boost/iostreams/operations.hpp>
#include <boost/shared_ptr.hpp>
#include <log4cplus/appender.h>
#include <log4cplus/helpers/property.h>


namespace log4cplus
Expand All @@ -51,7 +50,7 @@ struct device_type_traits
{
typedef T & device_type;

static
static inline
device_type
unwrap (device_type x)
{
Expand All @@ -65,7 +64,21 @@ struct device_type_traits<boost::shared_ptr<T> >
{
typedef boost::shared_ptr<T> device_type;

static
static inline
T &
unwrap (device_type const & ptr)
{
return *ptr;
}
};


template <typename T>
struct device_type_traits<std::shared_ptr<T> >
{
typedef std::shared_ptr<T> device_type;

static inline
T &
unwrap (device_type const & ptr)
{
Expand All @@ -77,6 +90,12 @@ struct device_type_traits<boost::shared_ptr<T> >
} // namespace device_appender_detail


/**
* @brief This appender wraps Boost IOStreams' Device concept instance
* as underlying sink for the appender.
*
* @tparam Device Boost IOStreams' Device concept instance
*/
template <typename Device>
class DeviceAppender
: public Appender
Expand All @@ -97,36 +116,53 @@ public:
, close_flag (close_device)
{ }

template <typename D>
DeviceAppender (std::shared_ptr<D> const & d, bool close_device = true)
: device (d)
, close_flag (close_device)
{ }

template <typename D>
DeviceAppender (D & d, const helpers::Properties & props)
: Appender (props)
, device (d)
, close_flag (true)
{
if (props.exists (LOG4CPLUS_TEXT ("CloseDevice")))
close_flag = true;
else
close_flag = false;
props.getBool (close_flag, LOG4CPLUS_TEXT ("CloseDevice"));
}

template <typename D>
DeviceAppender (boost::shared_ptr<D> const & d,
const helpers::Properties & props)
: Appender (props)
, device (d)
, close_flag (true)
{
props.getBool (close_flag, LOG4CPLUS_TEXT ("CloseDevice"));
}

template <typename D>
DeviceAppender (std::shared_ptr<D> const & d,
const helpers::Properties & props)
: Appender (props)
, device (d)
, close_flag (true)
{
if (props.exists (LOG4CPLUS_TEXT ("CloseDevice")))
close_flag = true;
else
close_flag = false;
props.getBool (close_flag, LOG4CPLUS_TEXT ("CloseDevice"));
}

DeviceAppender (DeviceAppender const &) = delete;
DeviceAppender & operator = (DeviceAppender const &) = delete;

virtual
~DeviceAppender ()
{ }
{
destructorImpl ();
}

virtual
void
close ()
close () override
{
if (close_flag)
boost::iostreams::close (device_traits::unwrap (device));
Expand All @@ -135,7 +171,7 @@ public:
protected:
virtual
void
append (log4cplus::spi::InternalLoggingEvent const & event)
append (log4cplus::spi::InternalLoggingEvent const & event) override
{
tstring & str = formatEvent (event);
boost::iostreams::write (device_traits::unwrap (device),
Expand All @@ -144,10 +180,6 @@ protected:

device_type device;
bool close_flag;

private:
DeviceAppender (DeviceAppender const &);
DeviceAppender & operator = (DeviceAppender const &);
};


Expand All @@ -156,8 +188,7 @@ inline
SharedAppenderPtr
make_device_appender (T & d, bool close_device = true)
{
SharedAppenderPtr app (new DeviceAppender<T> (d, close_device));
return app;
return SharedAppenderPtr (new DeviceAppender<T> (d, close_device));
}


Expand All @@ -166,8 +197,7 @@ inline
SharedAppenderPtr
make_device_appender (T & d, const helpers::Properties & props)
{
SharedAppenderPtr app (new DeviceAppender<T> (d, props));
return app;
return SharedAppenderPtr (new DeviceAppender<T> (d, props));
}


Expand All @@ -177,9 +207,8 @@ SharedAppenderPtr
make_device_appender_sp (boost::shared_ptr<T> const & p,
bool close_device = true)
{
SharedAppenderPtr app (
return SharedAppenderPtr (
new DeviceAppender<boost::shared_ptr<T> > (p, close_device));
return app;
}


Expand All @@ -189,9 +218,30 @@ SharedAppenderPtr
make_device_appender_sp (boost::shared_ptr<T> const & p,
const helpers::Properties & props)
{
SharedAppenderPtr app (
return SharedAppenderPtr (
new DeviceAppender<boost::shared_ptr<T> > (p, props));
return app;
}


template <typename T>
inline
SharedAppenderPtr
make_device_appender_sp (std::shared_ptr<T> const & p,
bool close_device = true)
{
return SharedAppenderPtr (
new DeviceAppender<std::shared_ptr<T> > (p, close_device));
}


template <typename T>
inline
SharedAppenderPtr
make_device_appender_sp (std::shared_ptr<T> const & p,
const helpers::Properties & props)
{
return SharedAppenderPtr (
new DeviceAppender<std::shared_ptr<T> > (p, props));
}


Expand Down
18 changes: 15 additions & 3 deletions tests/unit_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
add_executable (unit_tests unit_tests.cxx)
target_link_libraries (unit_tests ${log4cplus})
add_test(NAME unit_tests
set (unit_tests_sources unit_tests.cxx)
set (unit_tests_libs ${log4cplus})

find_package (Boost
REQUIRED COMPONENTS iostreams)
if (Boost_FOUND)
set (unit_tests_sources ${unit_tests_sources}
boost_tests.cxx)
set (unit_tests_libs ${unit_tests_libs}
Boost::iostreams)
endif (Boost_FOUND)

add_executable (unit_tests ${unit_tests_sources})
target_link_libraries (unit_tests PUBLIC ${unit_tests_libs})
add_test (NAME unit_tests
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
COMMAND unit_tests)
83 changes: 83 additions & 0 deletions tests/unit_tests/boost_tests.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright (C) 2023, Vaclav Haisman. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modifica-
// tion, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <log4cplus/config.hxx>

#include <log4cplus/loggingmacros.h>
#include <log4cplus/spi/loggingevent.h>
#include <log4cplus/boost/deviceappender.hxx>
#include <boost/iostreams/device/back_inserter.hpp>

#if defined (LOG4CPLUS_WITH_UNIT_TESTS)
#include <catch.hpp>


namespace log4cplus
{


namespace io = boost::iostreams;

CATCH_TEST_CASE ("DeviceAppender")
{
std::unique_ptr<Layout> layout {new SimpleLayout};

CATCH_SECTION ("direct")
{
tstring result;
auto device (io::back_inserter (result));
auto appender = make_device_appender (device);
appender->setLayout (std::move (layout));
appender->doAppend (spi::InternalLoggingEvent (LOG4CPLUS_TEXT ("logger"),
INFO_LOG_LEVEL, LOG4CPLUS_TEXT ("message"), __FILE__, __LINE__));
CATCH_REQUIRE (result.starts_with (LOG4CPLUS_TEXT ("INFO - message")));
}

CATCH_SECTION ("boost::shared_ptr")
{
tstring result;
boost::shared_ptr<io::back_insert_device<tstring>> device {
new io::back_insert_device<tstring> (result)};
auto appender = make_device_appender (device);
appender->setLayout (std::move (layout));
appender->doAppend (spi::InternalLoggingEvent (LOG4CPLUS_TEXT ("logger"),
INFO_LOG_LEVEL, LOG4CPLUS_TEXT ("message"), __FILE__, __LINE__));
CATCH_REQUIRE (result.starts_with (LOG4CPLUS_TEXT ("INFO - message")));
}

CATCH_SECTION ("std::shared_ptr")
{
tstring result;
std::shared_ptr<io::back_insert_device<tstring>> device {
new io::back_insert_device<tstring> (result)};
auto appender = make_device_appender (device);
appender->setLayout (std::move (layout));
appender->doAppend (spi::InternalLoggingEvent (LOG4CPLUS_TEXT ("logger"),
INFO_LOG_LEVEL, LOG4CPLUS_TEXT ("message"), __FILE__, __LINE__));
CATCH_REQUIRE (result.starts_with (LOG4CPLUS_TEXT ("INFO - message")));
}
}

} // namespace log4cplus

#endif // defined (LOG4CPLUS_WITH_UNIT_TESTS)

0 comments on commit 16d46d7

Please sign in to comment.