MINIFI-83: Allow appenders to be specified and auto configured.

This PR will modify logging so that we can have configurable
appenders and have them be modified via custom configuration
for that appender. Eventually these can be modified real time.

This closes #57.

Signed-off-by: Aldrin Piri <[email protected]>


Project: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/commit/f38859e4
Tree: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/tree/f38859e4
Diff: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/diff/f38859e4

Branch: refs/heads/master
Commit: f38859e432d437fc7a869016fc40f8dadfe89e72
Parents: 3facf2c
Author: Marc Parisi <[email protected]>
Authored: Fri Feb 24 10:06:19 2017 -0500
Committer: Aldrin Piri <[email protected]>
Committed: Mon Feb 27 14:40:12 2017 -0500

----------------------------------------------------------------------
 libminifi/include/AppendHostInfo.h           |   2 +-
 libminifi/include/BaseLogger.h               | 207 +++++++++++++++
 libminifi/include/Configure.h                |   4 +-
 libminifi/include/Connection.h               |   4 +-
 libminifi/include/ExecuteProcess.h           |   2 +-
 libminifi/include/FlowControlProtocol.h      |   4 +-
 libminifi/include/FlowController.h           |   5 +-
 libminifi/include/FlowFileRecord.h           |   2 +-
 libminifi/include/GetFile.h                  |   2 +-
 libminifi/include/ListenHTTP.h               |   6 +-
 libminifi/include/ListenSyslog.h             |   2 +-
 libminifi/include/LogAppenders.h             | 298 ++++++++++++++++++++++
 libminifi/include/LogAttribute.h             |   2 +-
 libminifi/include/Logger.h                   | 223 ++++++++--------
 libminifi/include/ProcessContext.h           |   2 +-
 libminifi/include/ProcessGroup.h             |   4 +-
 libminifi/include/ProcessSession.h           |   4 +-
 libminifi/include/Processor.h                |   2 +-
 libminifi/include/Property.h                 |   1 -
 libminifi/include/Provenance.h               |   6 +-
 libminifi/include/PutFile.h                  |   4 +-
 libminifi/include/RealTimeDataCollector.h    |   2 +-
 libminifi/include/RemoteProcessorGroupPort.h |  31 +--
 libminifi/include/ResourceClaim.h            |   2 +-
 libminifi/include/SchedulingAgent.h          |   3 +-
 libminifi/include/Site2SiteClientProtocol.h  |   4 +-
 libminifi/include/Site2SitePeer.h            |   3 +-
 libminifi/include/TailFile.h                 |   2 +-
 libminifi/include/ThreadedSchedulingAgent.h  |   2 +-
 libminifi/include/io/ClientSocket.h          |   2 +-
 libminifi/include/io/TLSSocket.h             |   2 +-
 libminifi/src/BaseLogger.cpp                 | 153 +++++++++++
 libminifi/src/Configure.cpp                  |   2 +-
 libminifi/src/FlowFileRecord.cpp             |   3 +-
 libminifi/src/LogAppenders.cpp               |  25 ++
 libminifi/src/Logger.cpp                     |   5 +-
 libminifi/src/Provenance.cpp                 |   3 +-
 libminifi/src/io/TLSSocket.cpp               |  16 +-
 libminifi/test/TestBase.h                    |   2 +-
 libminifi/test/unit/CRCTests.cpp             |  81 ++++++
 libminifi/test/unit/CRCTests.h               |  78 ------
 libminifi/test/unit/LoggerTests.cpp          | 143 +++++++++++
 libminifi/test/unit/ProcessorTests.cpp       | 150 +++++++++++
 libminifi/test/unit/ProcessorTests.h         | 154 -----------
 libminifi/test/unit/PropertyTests.cpp        | 103 ++++++++
 libminifi/test/unit/PropertyTests.h          | 106 --------
 libminifi/test/unit/ProvenanceTests.cpp      |  96 +++++++
 libminifi/test/unit/ProvenanceTests.h        |  96 -------
 libminifi/test/unit/SerializationTests.cpp   |  83 ++++++
 libminifi/test/unit/SerializationTests.h     |  88 -------
 libminifi/test/unit/SocketTests.cpp          | 186 ++++++++++++++
 libminifi/test/unit/SocketTests.h            | 190 --------------
 libminifi/test/unit/Tests.cpp                |  14 +-
 libminifi/test/unit/TimeUtilsTest.h          |  30 ---
 main/MiNiFiMain.cpp                          | 119 ++++-----
 55 files changed, 1773 insertions(+), 992 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/AppendHostInfo.h
----------------------------------------------------------------------
diff --git a/libminifi/include/AppendHostInfo.h 
b/libminifi/include/AppendHostInfo.h
index 5d62aae..8d9dd8f 100644
--- a/libminifi/include/AppendHostInfo.h
+++ b/libminifi/include/AppendHostInfo.h
@@ -61,7 +61,7 @@ protected:
 
 private:
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
 };
 
 #endif

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/BaseLogger.h
----------------------------------------------------------------------
diff --git a/libminifi/include/BaseLogger.h b/libminifi/include/BaseLogger.h
new file mode 100644
index 0000000..e9d2a02
--- /dev/null
+++ b/libminifi/include/BaseLogger.h
@@ -0,0 +1,207 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef LIBMINIFI_INCLUDE_BASELOGGER_H_
+#define LIBMINIFI_INCLUDE_BASELOGGER_H_
+
+#include <string>
+#include <memory>
+#include "spdlog/spdlog.h"
+#include <iostream>
+//! 5M default log file size
+#define DEFAULT_LOG_FILE_SIZE (5*1024*1024)
+//! 3 log files rotation
+#define DEFAULT_LOG_FILE_NUMBER 3
+#define LOG_NAME "minifi log"
+#define LOG_FILE_NAME "minifi-app.log"
+
+/**
+ * Log level enumeration.
+ */
+typedef enum {
+       trace = 0, debug = 1, info = 2, warn = 3, err = 4, critical = 5, off = 6
+} LOG_LEVEL_E;
+
+#define LOG_BUFFER_SIZE 1024
+#define FILL_BUFFER  char buffer[LOG_BUFFER_SIZE]; \
+    va_list args; \
+    va_start(args, format); \
+    std::vsnprintf(buffer, LOG_BUFFER_SIZE,format, args); \
+    va_end(args);
+
+/**
+ * Base class that represents a logger configuration.
+ */
+class BaseLogger {
+
+public:
+       static const char *nifi_log_level;
+       static const char *nifi_log_appender;
+
+       /**
+        * Base Constructor
+        */
+       BaseLogger() {
+               setLogLevel("info");
+               logger_ = nullptr;
+               stderr_ = nullptr;
+       }
+
+       /**
+        * Logger configuration constructorthat will set the base log level.
+        * @param config incoming configuration.
+        */
+       BaseLogger(std::string log_level, std::shared_ptr<spdlog::logger> 
logger) : logger_(logger) {
+               setLogLevel(log_level);
+
+       }
+
+       virtual ~BaseLogger() {
+
+       }
+
+       /**
+        * Move constructor that will atomically swap configuration
+        * shared pointers.
+        */
+       BaseLogger(const BaseLogger &&other) :
+                       configured_level_(other.configured_level_.load()) {
+               // must atomically exchange the pointers
+               logger_ = std::move(other.logger_);
+               set_error_logger(other.stderr_);
+
+       }
+
+       /**
+        * Returns the log level for this instance.
+        */
+       virtual LOG_LEVEL_E getLogLevel() const {
+               return configured_level_;
+       }
+
+       /**
+        * @brief Log error message
+        * @param format format string ('man printf' for syntax)
+        * @warning does not check @p log or @p format for null. Caller must 
ensure parameters and format string lengths match
+        */
+       virtual void log_error(const char * const format, ...);
+       /**
+        * @brief Log warn message
+        * @param format format string ('man printf' for syntax)
+        * @warning does not check @p log or @p format for null. Caller must 
ensure parameters and format string lengths match
+        */
+       virtual void log_warn(const char * const format, ...);
+       /**
+        * @brief Log info message
+        * @param format format string ('man printf' for syntax)
+        * @warning does not check @p log or @p format for null. Caller must 
ensure parameters and format string lengths match
+        */
+       virtual void log_info(const char * const format, ...);
+       /**
+        * @brief Log debug message
+        * @param format format string ('man printf' for syntax)
+        * @warning does not check @p log or @p format for null. Caller must 
ensure parameters and format string lengths match
+        */
+       virtual void log_debug(const char * const format, ...);
+       /**
+        * @brief Log trace message
+        * @param format format string ('man printf' for syntax)
+        * @warning does not check @p log or @p format for null. Caller must 
ensure parameters and format string lengths match
+        */
+       virtual void log_trace(const char * const format, ...);
+
+       /**
+        * @brief Log error message
+        * @param format format string ('man printf' for syntax)
+        * @warning does not check @p log or @p format for null. Caller must 
ensure parameters and format string lengths match
+        */
+       virtual void log_str(LOG_LEVEL_E level,const std::string &buffer);
+
+       /**
+        * Sets the log level for this instance based on the string
+        * @param level desired log leve.
+        * @param defaultLevel default level if we cannot match level.
+        */
+       virtual void setLogLevel(const std::string &level,
+                       LOG_LEVEL_E defaultLevel = info);
+
+       /**
+        * Sets the log level atomic and sets it
+        * within logger if it can
+        * @param level desired log level.
+        */
+       virtual void setLogLevel(LOG_LEVEL_E level) {
+               configured_level_ = level;
+               setLogLevel();
+       }
+
+       bool shouldLog(LOG_LEVEL_E level)
+       {
+               return level >= 
configured_level_.load(std::memory_order_relaxed);
+       }
+
+       /**
+        * Move operator overload
+        */
+       BaseLogger &operator=(const BaseLogger &&other) {
+               configured_level_ = (other.configured_level_.load());
+               // must atomically exchange the pointers
+               logger_ = std::move(other.logger_);
+               set_error_logger(other.stderr_);
+               return *this;
+       }
+
+protected:
+
+
+
+       /**
+        * Logger configuration constructorthat will set the base log level.
+        * @param config incoming configuration.
+        */
+       BaseLogger(std::string log_level) : logger_(nullptr) {
+               setLogLevel(log_level);
+       }
+
+
+       void setLogger(std::shared_ptr<spdlog::logger> logger) {
+               logger_ = logger;
+       }
+
+       /**
+        * Since a thread may be using stderr and it can be null,
+        * we must atomically exchange the shared pointers.
+        * @param other other shared pointer. can be null ptr
+        */
+       void set_error_logger(std::shared_ptr<spdlog::logger> other);
+
+       /**
+        * Sets the log level on the spdlogger if it is not null.
+        */
+       void setLogLevel() {
+               if (logger_ != nullptr)
+               logger_->set_level(
+                               (spdlog::level::level_enum) 
configured_level_.load());
+
+       }
+
+       std::atomic<LOG_LEVEL_E> configured_level_;
+       std::shared_ptr<spdlog::logger> logger_;
+       std::shared_ptr<spdlog::logger> stderr_;
+};
+
+#endif /* LIBMINIFI_INCLUDE_BASELOGGER_H_ */

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/Configure.h
----------------------------------------------------------------------
diff --git a/libminifi/include/Configure.h b/libminifi/include/Configure.h
index a60a6d5..9bb7a0e 100644
--- a/libminifi/include/Configure.h
+++ b/libminifi/include/Configure.h
@@ -27,6 +27,7 @@
 #include <errno.h>
 #include <iostream>
 #include <fstream>
+
 #include "Logger.h"
 
 class Configure {
@@ -45,7 +46,6 @@ public:
        static const char *nifi_administrative_yield_duration;
        static const char *nifi_bored_yield_duration;
        static const char *nifi_graceful_shutdown_seconds;
-       static const char *nifi_log_level;
        static const char *nifi_server_name;
        static const char *nifi_server_port;
        static const char *nifi_server_report_interval;
@@ -101,7 +101,7 @@ private:
        //! Mutex for protection
        std::mutex _mtx;
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
        //! Home location for this executable
        std::string _minifiHome;
 

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/Connection.h
----------------------------------------------------------------------
diff --git a/libminifi/include/Connection.h b/libminifi/include/Connection.h
index d372b77..0868560 100644
--- a/libminifi/include/Connection.h
+++ b/libminifi/include/Connection.h
@@ -29,8 +29,8 @@
 #include <algorithm>
 
 #include "FlowFileRecord.h"
-#include "Relationship.h"
 #include "Logger.h"
+#include "Relationship.h"
 
 //! Forwarder declaration
 class Processor;
@@ -190,7 +190,7 @@ private:
        //! Queue for the Flow File
        std::queue<FlowFileRecord *> _queue;
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
        // Prevent default copy constructor and assignment operation
        // Only support pass by reference or pointer
        Connection(const Connection &parent);

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/ExecuteProcess.h
----------------------------------------------------------------------
diff --git a/libminifi/include/ExecuteProcess.h 
b/libminifi/include/ExecuteProcess.h
index 83cf23c..3ddd815 100644
--- a/libminifi/include/ExecuteProcess.h
+++ b/libminifi/include/ExecuteProcess.h
@@ -94,7 +94,7 @@ protected:
 
 private:
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
        //! Property
        std::string _command;
        std::string _commandArgument;

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/FlowControlProtocol.h
----------------------------------------------------------------------
diff --git a/libminifi/include/FlowControlProtocol.h 
b/libminifi/include/FlowControlProtocol.h
index b3b0686..ffc454a 100644
--- a/libminifi/include/FlowControlProtocol.h
+++ b/libminifi/include/FlowControlProtocol.h
@@ -32,8 +32,8 @@
 #include <errno.h>
 #include <chrono>
 #include <thread>
-#include "Logger.h"
 #include "Configure.h"
+#include "Logger.h"
 #include "Property.h"
 
 //! Forwarder declaration
@@ -304,7 +304,7 @@ private:
        //! Mutex for protection
        std::mutex _mtx;
        //! Logger
-       Logger *logger_ = NULL;
+       std::shared_ptr<Logger> logger_;
        //! Configure
        Configure *configure_ = NULL;
        //! NiFi server Name

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/FlowController.h
----------------------------------------------------------------------
diff --git a/libminifi/include/FlowController.h 
b/libminifi/include/FlowController.h
index 56dba03..d60f022 100644
--- a/libminifi/include/FlowController.h
+++ b/libminifi/include/FlowController.h
@@ -219,7 +219,7 @@ protected:
 private:
 
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
 
 };
 
@@ -281,9 +281,8 @@ private:
        //! Mutex for protection
        std::mutex _mtx;
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
        Configure *configure_;
-
        //! Process Processor Node YAML
        void parseProcessorNodeYaml(YAML::Node processorNode, ProcessGroup 
*parent);
        //! Process Port YAML

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/FlowFileRecord.h
----------------------------------------------------------------------
diff --git a/libminifi/include/FlowFileRecord.h 
b/libminifi/include/FlowFileRecord.h
index 6626572..a3b87ee 100644
--- a/libminifi/include/FlowFileRecord.h
+++ b/libminifi/include/FlowFileRecord.h
@@ -216,7 +216,7 @@ private:
        //! Orginal connection queue that this flow file was dequeued from
        Connection *_orginalConnection;
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
        //! Snapshot flow record for session rollback
        bool _snapshot;
        // Prevent default copy constructor and assignment operation

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/GetFile.h
----------------------------------------------------------------------
diff --git a/libminifi/include/GetFile.h b/libminifi/include/GetFile.h
index 0d74110..8f8068c 100644
--- a/libminifi/include/GetFile.h
+++ b/libminifi/include/GetFile.h
@@ -82,7 +82,7 @@ protected:
 
 private:
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
        //! Queue for store directory list
        std::queue<std::string> _dirList;
        //! Get Listing size

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/ListenHTTP.h
----------------------------------------------------------------------
diff --git a/libminifi/include/ListenHTTP.h b/libminifi/include/ListenHTTP.h
index 57fd967..5a467f2 100644
--- a/libminifi/include/ListenHTTP.h
+++ b/libminifi/include/ListenHTTP.h
@@ -80,7 +80,7 @@ public:
                //! Send HTTP 500 error response to client
                void sendErrorResponse(struct mg_connection *conn);
                //! Logger
-               Logger *_logger;
+               std::shared_ptr<Logger> _logger;
 
                std::regex _authDNRegex;
                std::regex _headersAsAttributesRegex;
@@ -97,7 +97,7 @@ public:
 
        private:
                //! Logger
-               Logger *_logger;
+               std::shared_ptr<Logger> _logger;
 
                struct mg_connection *_conn;
                const struct mg_request_info *_reqInfo;
@@ -107,7 +107,7 @@ protected:
 
 private:
        //! Logger
-       Logger *_logger;
+       std::shared_ptr<Logger> _logger;
 
        std::unique_ptr<CivetServer> _server;
        std::unique_ptr<Handler> _handler;

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/ListenSyslog.h
----------------------------------------------------------------------
diff --git a/libminifi/include/ListenSyslog.h b/libminifi/include/ListenSyslog.h
index 309a3ad..339dbc1 100644
--- a/libminifi/include/ListenSyslog.h
+++ b/libminifi/include/ListenSyslog.h
@@ -130,7 +130,7 @@ protected:
 
 private:
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
        //! Run function for the thread
        static void run(ListenSyslog *process);
        //! Run Thread

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/LogAppenders.h
----------------------------------------------------------------------
diff --git a/libminifi/include/LogAppenders.h b/libminifi/include/LogAppenders.h
new file mode 100644
index 0000000..ef28bb8
--- /dev/null
+++ b/libminifi/include/LogAppenders.h
@@ -0,0 +1,298 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef LIBMINIFI_INCLUDE_LOGAPPENDERS_H_
+#define LIBMINIFI_INCLUDE_LOGAPPENDERS_H_
+
+#include "BaseLogger.h"
+#include "spdlog/sinks/null_sink.h"
+#include "spdlog/sinks/ostream_sink.h"
+#include <cxxabi.h>
+#include "Configure.h"
+
+template<typename T>
+static std::string getUniqueName() {
+       std::string name = LOG_NAME;
+       name += " -- ";
+       name += abi::__cxa_demangle(typeid(T).name(), 0, 0, 0);
+       spdlog::drop(name);
+       return name;
+}
+
+/**
+ * Null appender sets a null sink, thereby performing no logging.
+ */
+class NullAppender: public BaseLogger {
+public:
+       /**
+        * Base constructor that creates the null sink.
+        */
+       explicit NullAppender() :
+                       ::BaseLogger("off") {
+               auto null_sink = 
std::make_shared<spdlog::sinks::null_sink_st>();
+               std::string unique_name = getUniqueName<NullAppender>();
+               logger_ = std::make_shared<spdlog::logger>(unique_name, 
null_sink);
+               configured_level_ = off;
+               setLogLevel();
+       }
+
+       /**
+        * Move constructor for the null appender.
+        */
+       explicit NullAppender(const NullAppender &&other) :
+                       ::BaseLogger(std::move(other)) {
+
+       }
+
+};
+
+/**
+ * Basic output stream configuration that uses a supplied ostream
+ *
+ * Design : extends LoggerConfiguration using the logger and log level
+ * encapsulated within the base configuration class.
+ */
+class OutputStreamAppender: public BaseLogger {
+
+public:
+
+       static const char *nifi_log_output_stream_error_stderr;
+
+       /**
+        * Output stream move constructor.
+        */
+       explicit OutputStreamAppender(const OutputStreamAppender &&other) :
+                       ::BaseLogger(std::move(other)) {
+
+       }
+
+       /**
+        * Base constructor. Creates a ostream sink.
+        * @param stream incoming stream reference.
+        * @param config configuration.
+        */
+       explicit OutputStreamAppender(Configure *config) :
+                       ::BaseLogger("info") {
+               auto ostream_sink = 
std::make_shared<spdlog::sinks::ostream_sink_mt>(
+                               std::cout);
+
+               std::string unique_name = getUniqueName<OutputStreamAppender>();
+               logger_ = std::make_shared<spdlog::logger>(unique_name, 
ostream_sink);
+
+               std::string use_std_err;
+
+               if (NULL != config
+                               && 
config->get(nifi_log_output_stream_error_stderr,
+                                               use_std_err)) {
+
+                       std::transform(use_std_err.begin(), use_std_err.end(),
+                                       use_std_err.begin(), ::tolower);
+
+                       if (use_std_err == "true") {
+                               std::string err_unique_name =
+                                               
getUniqueName<OutputStreamAppender>();
+                               auto error_ostream_sink = std::make_shared<
+                                               
spdlog::sinks::ostream_sink_mt>(std::cerr);
+                               stderr_ = 
std::make_shared<spdlog::logger>(err_unique_name,
+                                               error_ostream_sink);
+                       }
+               } else {
+                       stderr_ = nullptr;
+               }
+
+               std::string log_level;
+               if (NULL != config
+                               && config->get(BaseLogger::nifi_log_level, 
log_level)) {
+                       setLogLevel(log_level);
+               } else{
+                       setLogLevel("info");
+               }
+
+       }
+
+       /**
+        * Base constructor. Creates a ostream sink.
+        * @param stream incoming stream reference.
+        * @param config configuration.
+        */
+       OutputStreamAppender(std::ostream &stream, Configure *config) :
+                       ::BaseLogger("info") {
+               auto ostream_sink = 
std::make_shared<spdlog::sinks::ostream_sink_mt>(
+                               stream);
+               std::string unique_name = getUniqueName<OutputStreamAppender>();
+               logger_ = std::make_shared<spdlog::logger>(unique_name, 
ostream_sink);
+
+               stderr_ = nullptr;
+
+               std::string log_level;
+               if (NULL != config
+                               && config->get(BaseLogger::nifi_log_level, 
log_level)) {
+                       setLogLevel(log_level);
+               } else {
+                       setLogLevel("info");
+               }
+
+       }
+
+protected:
+
+};
+
+/**
+ * Rolling configuration
+ * Design : extends LoggerConfiguration using the logger and log level
+ * encapsulated within the base configuration class.
+ */
+class RollingAppender: public BaseLogger {
+public:
+       static const char *nifi_log_rolling_apender_file;
+       static const char *nifi_log_rolling_appender_max_files;
+       static const char *nifi_log_rolling_appender_max_file_size;
+
+       /**
+        * RollingAppenderConfiguration move constructor.
+        */
+       explicit RollingAppender(const RollingAppender&& other) :
+                       ::BaseLogger(std::move(other)), max_files_(
+                                       std::move(other.max_files_)), 
file_name_(
+                                       std::move(other.file_name_)), 
max_file_size_(
+                                       std::move(other.max_file_size_)) {
+       }
+       /**
+        * Base Constructor.
+        * @param config pointer to the configuration for this instance.
+        */
+       explicit RollingAppender(Configure * config = 0) :
+                       ::BaseLogger("info") {
+               std::string file_name = "";
+               if (NULL != config
+                               && config->get(nifi_log_rolling_apender_file, 
file_name)) {
+                       file_name_ = file_name;
+               } else{
+                       file_name_ = LOG_FILE_NAME;
+               }
+
+               std::string max_files = "";
+               if (NULL != config
+                               && 
config->get(nifi_log_rolling_appender_max_files,
+                                               max_files)) {
+                       try {
+                               max_files_ = std::stoi(max_files);
+                       } catch (const std::invalid_argument &ia) {
+                               max_files_ = DEFAULT_LOG_FILE_NUMBER;
+                       } catch (const std::out_of_range &oor) {
+                               max_files_ = DEFAULT_LOG_FILE_NUMBER;
+                       }
+               } else {
+                       max_files_ = DEFAULT_LOG_FILE_NUMBER;
+               }
+
+               std::string max_file_size = "";
+               if (NULL != config
+                               && 
config->get(nifi_log_rolling_appender_max_file_size,
+                                               max_file_size)) {
+                       try {
+                               max_file_size_ = std::stoi(max_file_size);
+                       } catch (const std::invalid_argument &ia) {
+                               max_file_size_ = DEFAULT_LOG_FILE_SIZE;
+                       } catch (const std::out_of_range &oor) {
+                               max_file_size_ = DEFAULT_LOG_FILE_SIZE;
+                       }
+               } else {
+                       max_file_size_ = DEFAULT_LOG_FILE_SIZE;
+               }
+
+               std::string unique_name = getUniqueName<OutputStreamAppender>();
+               logger_ = spdlog::rotating_logger_mt(unique_name, file_name_,
+                               max_file_size_, max_files_);
+
+               std::string log_level;
+               if (NULL != config
+                               && config->get(BaseLogger::nifi_log_level, 
log_level)) {
+                       setLogLevel(log_level);
+               }
+       }
+
+       /**
+        * To maintain current functionality we will flush on write.
+        */
+       void log_str(LOG_LEVEL_E level, const std::string &buffer) {
+               ::BaseLogger::log_str(level, buffer);
+               logger_->flush();
+       }
+
+protected:
+
+       /**
+        * file name.
+        */
+       std::string file_name_;
+       /**
+        * maximum number of files to keep in the rotation.
+        */
+       size_t max_files_;
+       /**
+        * Maximum file size per rotated file.
+        */
+       size_t max_file_size_;
+
+};
+
+class LogInstance {
+public:
+       /**
+        * Returns a logger configuration based on
+        * the configuration within this instance.
+        * @param config configuration for this instance.
+        */
+       static std::unique_ptr<BaseLogger> getConfiguredLogger(Configure 
*config) {
+               std::string appender = "";
+
+               if (config->get(BaseLogger::nifi_log_appender, appender)) {
+                       std::transform(appender.begin(), appender.end(), 
appender.begin(),
+                                       ::tolower);
+
+                       if ("nullappender" == appender || "null appender" == 
appender
+                                       || "null" == appender) {
+
+                               return std::move(
+                                               std::unique_ptr<BaseLogger>(new 
NullAppender()));
+
+                       } else if ("rollingappender" == appender
+                                       || "rolling appender" == appender
+                                       || "rolling" == appender) {
+
+                               return std::move(
+                                               std::unique_ptr<BaseLogger>(
+                                                               new 
RollingAppender(config)));
+
+                       } else if ("outputstream" == appender
+                                       || "outputstreamappender" == appender
+                                       || "outputstream appender" == appender) 
{
+
+                               return std::move(
+                                               std::unique_ptr<BaseLogger>(
+                                                               new 
OutputStreamAppender(config)));
+
+                       }
+               }
+               return nullptr;
+
+       }
+};
+
+#endif /* LIBMINIFI_INCLUDE_LOGAPPENDERS_H_ */

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/LogAttribute.h
----------------------------------------------------------------------
diff --git a/libminifi/include/LogAttribute.h b/libminifi/include/LogAttribute.h
index 2478c7a..429a594 100644
--- a/libminifi/include/LogAttribute.h
+++ b/libminifi/include/LogAttribute.h
@@ -122,7 +122,7 @@ protected:
 
 private:
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
 };
 
 #endif

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/Logger.h
----------------------------------------------------------------------
diff --git a/libminifi/include/Logger.h b/libminifi/include/Logger.h
index 91d0e72..81d4446 100644
--- a/libminifi/include/Logger.h
+++ b/libminifi/include/Logger.h
@@ -22,166 +22,179 @@
 #define __LOGGER_H__
 
 #include <string>
+#include <atomic>
+#include <memory>
+#include <utility>
 #include <algorithm>
 #include <cstdio>
-#include "spdlog/spdlog.h"
+#include <iostream>
 
-using spdlog::stdout_logger_mt;
-using spdlog::rotating_logger_mt;
-using spdlog::logger;
-
-#define LOG_BUFFER_SIZE 1024
-#define FILL_BUFFER  char buffer[LOG_BUFFER_SIZE]; \
-    va_list args; \
-    va_start(args, format); \
-    std::vsnprintf(buffer, LOG_BUFFER_SIZE,format, args); \
-    va_end(args);
-
-//! 5M default log file size
-#define DEFAULT_LOG_FILE_SIZE (5*1024*1024)
-//! 3 log files rotation
-#define DEFAULT_LOG_FILE_NUMBER 3
-#define LOG_NAME "minifi log"
-#define LOG_FILE_NAME "minifi-app.log"
-
-typedef enum
-{
-    trace    = 0,
-    debug    = 1,
-    info     = 2,
-    notice   = 3,
-    warn     = 4,
-    err      = 5,
-    critical = 6,
-    alert    = 7,
-    emerg    = 8,
-    off      = 9
-} LOG_LEVEL_E;
-
-//! Logger Class
-class Logger {
+#include "BaseLogger.h"
+#include "spdlog/spdlog.h"
 
+/**
+ * Logger class
+ * Design: Extends BaseLogger, leaving this class to be the facade to the 
underlying
+ * logging mechanism. Is a facade to BaseLogger's underlying log stream. This 
allows
+ * the underlying implementation to be replaced real time.
+ */
+class Logger: public BaseLogger {
+protected:
+       struct singleton;
 public:
 
-       //! Get the singleton logger instance
-       static Logger * getLogger() {
-               if (!logger_)
-                       logger_ = new Logger();
-               return logger_;
+       /**
+        * Returns a shared pointer to the logger instance.
+        * Note that while there is no synchronization this is expected
+        * to be called and initialized first
+        * @returns shared pointer to the base logger.
+        */
+       static std::shared_ptr<Logger> getLogger() {
+
+               if (singleton_logger_ == nullptr)
+                       singleton_logger_ = std::make_shared<Logger>(singleton 
{ 0 });
+               return singleton_logger_;
+       }
+
+       /**
+        * Returns the log level for this instance.
+        */
+       LOG_LEVEL_E getLogLevel() const {
+               return current_logger_.load()->getLogLevel();
        }
+
+       /**
+        * Sets the log level atomic and sets it
+        * within logger if it can
+        * @param level desired log level.
+        */
        void setLogLevel(LOG_LEVEL_E level) {
-               if (spdlog_ == NULL)
-                       return;
-               spdlog_->set_level((spdlog::level::level_enum) level);
+               current_logger_.load()->setLogLevel(level);
        }
 
-       void setLogLevel(const std::string &level,LOG_LEVEL_E defaultLevel = 
info )
-       {
-               std::string logLevel = "";
-               std::transform(level.begin(), level.end(), logLevel.end(), 
::tolower);
-
-               if (logLevel == "trace") {
-                       setLogLevel(trace);
-               } else if (logLevel == "debug") {
-                       setLogLevel(debug);
-               } else if (logLevel == "info") {
-                       setLogLevel(info);
-               } else if (logLevel == "notice") {
-                       setLogLevel(notice);
-               } else if (logLevel == "warn") {
-                       setLogLevel(warn);
-               } else if (logLevel == "error") {
-                       setLogLevel(err);
-               } else if (logLevel == "critical") {
-                       setLogLevel(critical);
-               } else if (logLevel == "alert") {
-                       setLogLevel(alert);
-               } else if (logLevel == "emerg") {
-                       setLogLevel(emerg);
-               } else if (logLevel == "off") {
-                       setLogLevel(off);
-               } else {
-                       setLogLevel(defaultLevel);
-               }
+       /**
+        * Sets the log level for this instance based on the string
+        * @param level desired log leve.
+        * @param defaultLevel default level if we cannot match level.
+        */
+       void setLogLevel(const std::string &level,
+                       LOG_LEVEL_E defaultLevel = info) {
+               current_logger_.load()->setLogLevel(level, info);
        }
-       //! Destructor
-       ~Logger() {}
+
+       void updateLogger(std::unique_ptr<BaseLogger> logger) {
+
+               if (logger == nullptr  )
+                       return;
+               current_logger_.store(logger.release());
+       }
+
        /**
         * @brief Log error message
         * @param format format string ('man printf' for syntax)
         * @warning does not check @p log or @p format for null. Caller must 
ensure parameters and format string lengths match
         */
-       void log_error(const char *const format, ...) {
-               if(spdlog_ == NULL || 
!spdlog_->should_log(spdlog::level::level_enum::err))
+       void log_error(const char * const format, ...) {
+               if (!current_logger_.load()->shouldLog(err))
                        return;
                FILL_BUFFER
-           spdlog_->error(buffer);
+               current_logger_.load()->log_str(err, buffer);
        }
        /**
         * @brief Log warn message
         * @param format format string ('man printf' for syntax)
         * @warning does not check @p log or @p format for null. Caller must 
ensure parameters and format string lengths match
         */
-       void log_warn(const char *const format, ...) {
-               if(spdlog_ == NULL || 
!spdlog_->should_log(spdlog::level::level_enum::warn))
+       void log_warn(const char * const format, ...) {
+               if (!current_logger_.load()->shouldLog(warn))
                        return;
                FILL_BUFFER
-           spdlog_->warn(buffer);
+               current_logger_.load()->log_str(warn, buffer);
        }
        /**
         * @brief Log info message
         * @param format format string ('man printf' for syntax)
         * @warning does not check @p log or @p format for null. Caller must 
ensure parameters and format string lengths match
         */
-       void log_info(const char *const format, ...) {
-               if(spdlog_ == NULL || 
!spdlog_->should_log(spdlog::level::level_enum::info))
+       void log_info(const char * const format, ...) {
+               if (!current_logger_.load()->shouldLog(info))
                        return;
                FILL_BUFFER
-           spdlog_->info(buffer);
+               current_logger_.load()->log_str(info, buffer);
        }
        /**
         * @brief Log debug message
         * @param format format string ('man printf' for syntax)
         * @warning does not check @p log or @p format for null. Caller must 
ensure parameters and format string lengths match
         */
-       void log_debug(const char *const format, ...) {
-               if(spdlog_ == NULL || 
!spdlog_->should_log(spdlog::level::level_enum::debug))
+       void log_debug(const char * const format, ...) {
+
+               if (!current_logger_.load()->shouldLog(debug))
                        return;
                FILL_BUFFER
-           spdlog_->debug(buffer);
+               current_logger_.load()->log_str(debug, buffer);
        }
        /**
         * @brief Log trace message
         * @param format format string ('man printf' for syntax)
         * @warning does not check @p log or @p format for null. Caller must 
ensure parameters and format string lengths match
         */
-       void log_trace(const char *const format, ...) {
-               if(spdlog_ == NULL || 
!spdlog_->should_log(spdlog::level::level_enum::trace))
+       void log_trace(const char * const format, ...) {
+
+               if (!current_logger_.load()->shouldLog(trace))
                        return;
                FILL_BUFFER
-           spdlog_->trace(buffer);
+               current_logger_.load()->log_str(trace, buffer);
        }
 
-protected:
+       /**
+        * @brief Log message
+        * @param format format string ('man printf' for syntax)
+        * @warning does not check @p log or @p format for null. Caller must 
ensure parameters and format string lengths match
+        */
+       virtual void log_str(LOG_LEVEL_E level, const std::string &buffer) {
+               current_logger_.load()->log_str(level, buffer);
+       }
 
-private:
-       // Prevent default copy constructor and assignment operation
-       // Only support pass by reference or pointer
-       Logger(const Logger &parent);
-       Logger &operator=(const Logger &parent);
-       //! Constructor
-       /*!
-        * Create a logger
-        * */
-       Logger(const std::string logger_name = LOG_NAME, const std::string 
filename = LOG_FILE_NAME, size_t max_file_size = DEFAULT_LOG_FILE_SIZE, size_t 
max_files = DEFAULT_LOG_FILE_NUMBER, bool force_flush = true) {
-               spdlog_ = rotating_logger_mt(logger_name, filename, 
max_file_size, max_files);
-               spdlog_->set_level((spdlog::level::level_enum) debug);
+       //! Destructor
+       ~Logger() {
        }
-       //! spdlog
-       std::shared_ptr<logger> spdlog_;
 
-       //! Singleton logger instance
-       static Logger *logger_;
+       explicit Logger(const singleton &a) {
+
+               /**
+                * flush on info to maintain current functionality
+                */
+               std::shared_ptr<spdlog::logger> defaultsink = 
spdlog::rotating_logger_mt(LOG_NAME,
+                               LOG_FILE_NAME,
+                               DEFAULT_LOG_FILE_SIZE, DEFAULT_LOG_FILE_NUMBER);
+               defaultsink->flush_on(spdlog::level::level_enum::info);
+
+               std::unique_ptr<BaseLogger> new_logger_ = 
std::unique_ptr<BaseLogger>(
+                               new BaseLogger("info", defaultsink));
+
+               new_logger_->setLogLevel(info);
+               current_logger_.store(new_logger_.release());
+       }
+
+       Logger(const Logger &parent) = delete;
+       Logger &operator=(const Logger &parent) = delete;
+
+protected:
+
+       /**
+        * Allows for a null constructor above so that we can have a public 
constructor that
+        * effectively limits us to being a singleton by having a protected 
argument in the constructor
+        */
+       struct singleton {
+               explicit singleton(int) {
+               }
+       };
+
+       std::atomic<BaseLogger*> current_logger_;
+
+//! Singleton logger instance
+       static std::shared_ptr<Logger> singleton_logger_;
 };
 
 #endif

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/ProcessContext.h
----------------------------------------------------------------------
diff --git a/libminifi/include/ProcessContext.h 
b/libminifi/include/ProcessContext.h
index 469c87e..585e187 100644
--- a/libminifi/include/ProcessContext.h
+++ b/libminifi/include/ProcessContext.h
@@ -106,7 +106,7 @@ private:
        //! Processor
        Processor *_processor;
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
 
 };
 

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/ProcessGroup.h
----------------------------------------------------------------------
diff --git a/libminifi/include/ProcessGroup.h b/libminifi/include/ProcessGroup.h
index 28661ae..dbff7b0 100644
--- a/libminifi/include/ProcessGroup.h
+++ b/libminifi/include/ProcessGroup.h
@@ -29,11 +29,11 @@
 #include <algorithm>
 #include <set>
 
-#include "Logger.h"
 #include "Processor.h"
 #include "Exception.h"
 #include "TimerDrivenSchedulingAgent.h"
 #include "EventDrivenSchedulingAgent.h"
+#include "Logger.h"
 
 //! Process Group Type
 enum ProcessGroupType
@@ -175,7 +175,7 @@ private:
        //! Mutex for protection
        std::mutex mtx_;
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
        // Prevent default copy constructor and assignment operation
        // Only support pass by reference or pointer
        ProcessGroup(const ProcessGroup &parent);

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/ProcessSession.h
----------------------------------------------------------------------
diff --git a/libminifi/include/ProcessSession.h 
b/libminifi/include/ProcessSession.h
index 7146553..6f01506 100644
--- a/libminifi/include/ProcessSession.h
+++ b/libminifi/include/ProcessSession.h
@@ -29,11 +29,11 @@
 #include <algorithm>
 #include <set>
 
-#include "Logger.h"
 #include "Processor.h"
 #include "ProcessContext.h"
 #include "FlowFileRecord.h"
 #include "Exception.h"
+#include "Logger.h"
 #include "Provenance.h"
 
 //! ProcessSession Class
@@ -121,7 +121,7 @@ private:
        //! ProcessContext
        ProcessContext *_processContext;
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
        //! Provenance Report
        ProvenanceReporter *_provenanceReport;
 

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/Processor.h
----------------------------------------------------------------------
diff --git a/libminifi/include/Processor.h b/libminifi/include/Processor.h
index b675b7c..1634bc0 100644
--- a/libminifi/include/Processor.h
+++ b/libminifi/include/Processor.h
@@ -354,7 +354,7 @@ private:
        //! Check all incoming connections for work
        bool isWorkAvailable();
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
        // Prevent default copy constructor and assignment operation
        // Only support pass by reference or pointer
        Processor(const Processor &parent);

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/Property.h
----------------------------------------------------------------------
diff --git a/libminifi/include/Property.h b/libminifi/include/Property.h
index 93f9c0e..bf33b35 100644
--- a/libminifi/include/Property.h
+++ b/libminifi/include/Property.h
@@ -244,7 +244,6 @@ public:
                return false;
        }
 
-
 protected:
        //! Name
        std::string _name;

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/Provenance.h
----------------------------------------------------------------------
diff --git a/libminifi/include/Provenance.h b/libminifi/include/Provenance.h
index 10945c3..52489fc 100644
--- a/libminifi/include/Provenance.h
+++ b/libminifi/include/Provenance.h
@@ -451,7 +451,7 @@ protected:
 private:
 
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
        
        // Prevent default copy constructor and assignment operation
        // Only support pass by reference or pointer
@@ -555,7 +555,7 @@ private:
        //! Incoming connection Iterator
        std::set<ProvenanceEventRecord *> _events;
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
 
        // Prevent default copy constructor and assignment operation
        // Only support pass by reference or pointer
@@ -710,7 +710,7 @@ private:
        //! repository directory
        std::string _directory;
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
        //! Configure
        //! max db entry life time
        Configure *configure_;

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/PutFile.h
----------------------------------------------------------------------
diff --git a/libminifi/include/PutFile.h b/libminifi/include/PutFile.h
index bf48f79..015605e 100644
--- a/libminifi/include/PutFile.h
+++ b/libminifi/include/PutFile.h
@@ -69,7 +69,7 @@ public:
                bool commit();
 
        private:
-               Logger *logger_;
+               std::shared_ptr<Logger> logger_;
                std::ofstream _tmpFileOs;
                bool _writeSucceeded = false;
                std::string _tmpFile;
@@ -80,7 +80,7 @@ protected:
 
 private:
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
 
        bool putFile(ProcessSession *session, FlowFileRecord *flowFile, const 
std::string &tmpFile, const std::string &destFile);
 };

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/RealTimeDataCollector.h
----------------------------------------------------------------------
diff --git a/libminifi/include/RealTimeDataCollector.h 
b/libminifi/include/RealTimeDataCollector.h
index 6458f6d..3b6d05f 100644
--- a/libminifi/include/RealTimeDataCollector.h
+++ b/libminifi/include/RealTimeDataCollector.h
@@ -113,7 +113,7 @@ private:
        int _realTimeSocket;
        int _batchSocket;
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
        //! Mutex for protection
        std::mutex _mtx;
        //! Queued data size

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/RemoteProcessorGroupPort.h
----------------------------------------------------------------------
diff --git a/libminifi/include/RemoteProcessorGroupPort.h 
b/libminifi/include/RemoteProcessorGroupPort.h
index 73e8ac2..05ecd17 100644
--- a/libminifi/include/RemoteProcessorGroupPort.h
+++ b/libminifi/include/RemoteProcessorGroupPort.h
@@ -27,23 +27,21 @@
 #include "Site2SiteClientProtocol.h"
 
 //! RemoteProcessorGroupPort Class
-class RemoteProcessorGroupPort : public Processor
-{
+class RemoteProcessorGroupPort: public Processor {
 public:
        //! Constructor
        /*!
         * Create a new processor
         */
-       RemoteProcessorGroupPort(std::string name, uuid_t uuid = NULL)
-       : Processor(name, uuid), direction_(SEND),transmitting_(false), peer_()
-       {
-           logger_ = Logger::getLogger();
-           protocol_ = std::unique_ptr<Site2SiteClientProtocol>(new 
Site2SiteClientProtocol(0));
-           protocol_->setPortId(uuid);
+       RemoteProcessorGroupPort(std::string name, uuid_t uuid = NULL) :
+                       Processor(name, uuid), direction_(SEND), 
transmitting_(false), peer_() {
+               logger_ = Logger::getLogger();
+               protocol_ = std::unique_ptr<Site2SiteClientProtocol>(
+                               new Site2SiteClientProtocol(0));
+               protocol_->setPortId(uuid);
        }
        //! Destructor
-       virtual ~RemoteProcessorGroupPort()
-       {
+       virtual ~RemoteProcessorGroupPort() {
 
        }
        //! Processor Name
@@ -59,20 +57,17 @@ public:
        //! Initialize, over write by NiFi RemoteProcessorGroupPort
        virtual void initialize(void);
        //! Set Direction
-       void setDirection(TransferDirection direction)
-       {
+       void setDirection(TransferDirection direction) {
                direction_ = direction;
                if (direction_ == RECEIVE)
                        this->setTriggerWhenEmpty(true);
        }
        //! Set Timeout
-       void setTimeOut(uint64_t timeout)
-       {
+       void setTimeOut(uint64_t timeout) {
                protocol_->setTimeOut(timeout);
        }
        //! SetTransmitting
-       void setTransmitting(bool val)
-       {
+       void setTransmitting(bool val) {
                transmitting_ = val;
        }
 
@@ -80,8 +75,8 @@ protected:
 
 private:
        //! Logger
-       Logger *logger_;
-       
+       std::shared_ptr<Logger> logger_;
+       //! Peer Connection
        Site2SitePeer peer_;
        //! Peer Protocol
        std::unique_ptr<Site2SiteClientProtocol> protocol_;

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/ResourceClaim.h
----------------------------------------------------------------------
diff --git a/libminifi/include/ResourceClaim.h 
b/libminifi/include/ResourceClaim.h
index dcbb558..1dd2704 100644
--- a/libminifi/include/ResourceClaim.h
+++ b/libminifi/include/ResourceClaim.h
@@ -83,7 +83,7 @@ private:
        //! Configure
        Configure *configure_;
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
        // Prevent default copy constructor and assignment operation
        // Only support pass by reference or pointer
        ResourceClaim(const ResourceClaim &parent);

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/SchedulingAgent.h
----------------------------------------------------------------------
diff --git a/libminifi/include/SchedulingAgent.h 
b/libminifi/include/SchedulingAgent.h
index c814fa3..f6d5a1c 100644
--- a/libminifi/include/SchedulingAgent.h
+++ b/libminifi/include/SchedulingAgent.h
@@ -31,6 +31,7 @@
 #include "Logger.h"
 #include "Configure.h"
 #include "FlowFileRecord.h"
+#include "Logger.h"
 #include "Processor.h"
 #include "ProcessContext.h"
 
@@ -75,7 +76,7 @@ public:
 
 protected:
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
        //! Configure
        Configure *configure_;
        //! Mutex for protection

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/Site2SiteClientProtocol.h
----------------------------------------------------------------------
diff --git a/libminifi/include/Site2SiteClientProtocol.h 
b/libminifi/include/Site2SiteClientProtocol.h
index fc1c411..444eed5 100644
--- a/libminifi/include/Site2SiteClientProtocol.h
+++ b/libminifi/include/Site2SiteClientProtocol.h
@@ -34,11 +34,11 @@
 #include <thread>
 #include <algorithm>
 #include <uuid/uuid.h>
-#include "Logger.h"
 #include "Configure.h"
 #include "Property.h"
 #include "Site2SitePeer.h"
 #include "FlowFileRecord.h"
+#include "Logger.h"
 #include "ProcessContext.h"
 #include "ProcessSession.h"
 #include "io/CRCStream.h"
@@ -588,7 +588,7 @@ private:
        //! Mutex for protection
        std::mutex _mtx;
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
        //! Configure
        Configure *configure_;
        //! Batch Count

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/Site2SitePeer.h
----------------------------------------------------------------------
diff --git a/libminifi/include/Site2SitePeer.h 
b/libminifi/include/Site2SitePeer.h
index bd49e55..e89bb74 100644
--- a/libminifi/include/Site2SitePeer.h
+++ b/libminifi/include/Site2SitePeer.h
@@ -37,6 +37,7 @@
 #include "utils/TimeUtil.h"
 
 
+
 static const char MAGIC_BYTES[] = { 'N', 'i', 'F', 'i' };
 
 //! Site2SitePeer Class
@@ -251,7 +252,7 @@ private:
        //! socket timeout;
        std::atomic<uint64_t> _timeOut;
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
        //! Configure
        Configure *configure_;
        //! Yield Period in Milliseconds

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/TailFile.h
----------------------------------------------------------------------
diff --git a/libminifi/include/TailFile.h b/libminifi/include/TailFile.h
index c2fe555..d68748e 100644
--- a/libminifi/include/TailFile.h
+++ b/libminifi/include/TailFile.h
@@ -65,7 +65,7 @@ protected:
 
 private:
        //! Logger
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
        std::string _fileLocation;
        //! Property Specified Tailed File Name
        std::string _fileName;

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/ThreadedSchedulingAgent.h
----------------------------------------------------------------------
diff --git a/libminifi/include/ThreadedSchedulingAgent.h 
b/libminifi/include/ThreadedSchedulingAgent.h
index 78d56f2..5eb5d8a 100644
--- a/libminifi/include/ThreadedSchedulingAgent.h
+++ b/libminifi/include/ThreadedSchedulingAgent.h
@@ -20,8 +20,8 @@
 #ifndef __THREADED_SCHEDULING_AGENT_H__
 #define __THREADED_SCHEDULING_AGENT_H__
 
-#include "Logger.h"
 #include "Configure.h"
+#include "Logger.h"
 #include "Processor.h"
 #include "ProcessContext.h"
 #include "SchedulingAgent.h"

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/io/ClientSocket.h
----------------------------------------------------------------------
diff --git a/libminifi/include/io/ClientSocket.h 
b/libminifi/include/io/ClientSocket.h
index f73b0b4..7d3dbe2 100644
--- a/libminifi/include/io/ClientSocket.h
+++ b/libminifi/include/io/ClientSocket.h
@@ -222,7 +222,7 @@ protected:
         */
        virtual short select_descriptor(const uint16_t msec);
 
-       Logger *logger_;
+       std::shared_ptr<Logger> logger_;
 
        addrinfo *addr_info_;
 

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/include/io/TLSSocket.h
----------------------------------------------------------------------
diff --git a/libminifi/include/io/TLSSocket.h b/libminifi/include/io/TLSSocket.h
index 909cfc2..56845fe 100644
--- a/libminifi/include/io/TLSSocket.h
+++ b/libminifi/include/io/TLSSocket.h
@@ -103,7 +103,7 @@ private:
 
        TLSContext();
 
-       Logger *logger;
+       std::shared_ptr<Logger> logger_;
        Configure *configuration;
        SSL_CTX *ctx;
 

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/src/BaseLogger.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/BaseLogger.cpp b/libminifi/src/BaseLogger.cpp
new file mode 100644
index 0000000..1b3b2fd
--- /dev/null
+++ b/libminifi/src/BaseLogger.cpp
@@ -0,0 +1,153 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BaseLogger.h"
+
+// Logger related configuration items.
+const char *BaseLogger::nifi_log_level = "nifi.log.level";
+const char *BaseLogger::nifi_log_appender = "nifi.log.appender";
+
+/**
+ * @brief Log error message
+ * @param format format string ('man printf' for syntax)
+ * @warning does not check @p log or @p format for null. Caller must ensure 
parameters and format string lengths match
+ */
+ void BaseLogger::log_error(const char * const format, ...) {
+       if (logger_ == NULL || 
!logger_->should_log(spdlog::level::level_enum::err))
+               return;
+       FILL_BUFFER
+       log_str(err,buffer);
+}
+/**
+ * @brief Log warn message
+ * @param format format string ('man printf' for syntax)
+ * @warning does not check @p log or @p format for null. Caller must ensure 
parameters and format string lengths match
+ */
+ void BaseLogger::log_warn(const char * const format, ...) {
+       if (logger_ == NULL
+                       || 
!logger_->should_log(spdlog::level::level_enum::warn))
+               return;
+       FILL_BUFFER
+       log_str(warn,buffer);
+}
+/**
+ * @brief Log info message
+ * @param format format string ('man printf' for syntax)
+ * @warning does not check @p log or @p format for null. Caller must ensure 
parameters and format string lengths match
+ */
+ void BaseLogger::log_info(const char * const format, ...) {
+       if (logger_ == NULL
+                       || 
!logger_->should_log(spdlog::level::level_enum::info))
+               return;
+       FILL_BUFFER
+       log_str(info,buffer);
+}
+/**
+ * @brief Log debug message
+ * @param format format string ('man printf' for syntax)
+ * @warning does not check @p log or @p format for null. Caller must ensure 
parameters and format string lengths match
+ */
+ void BaseLogger::log_debug(const char * const format, ...) {
+
+       if (logger_ == NULL
+                       || 
!logger_->should_log(spdlog::level::level_enum::debug))
+               return;
+       FILL_BUFFER
+       log_str(debug,buffer);
+}
+/**
+ * @brief Log trace message
+ * @param format format string ('man printf' for syntax)
+ * @warning does not check @p log or @p format for null. Caller must ensure 
parameters and format string lengths match
+ */
+ void BaseLogger::log_trace(const char * const format, ...) {
+
+       if (logger_ == NULL
+                       || 
!logger_->should_log(spdlog::level::level_enum::trace))
+               return;
+       FILL_BUFFER
+       log_str(debug,buffer);
+}
+
+// overridables
+
+/**
+ * @brief Log error message
+ * @param format format string ('man printf' for syntax)
+ * @warning does not check @p log or @p format for null. Caller must ensure 
parameters and format string lengths match
+ */
+void BaseLogger::log_str(LOG_LEVEL_E level, const std::string &buffer) {
+       switch (level) {
+       case err:
+       case critical:
+               if (stderr_ != nullptr) {
+                       stderr_->error(buffer);
+               } else {
+                       logger_->error(buffer);
+               }
+               break;
+       case warn:
+               logger_->warn(buffer);
+               break;
+       case info:
+               logger_->info(buffer);
+               break;
+       case debug:
+               logger_->debug(buffer);
+               break;
+       case trace:
+               logger_->trace(buffer);
+               break;
+       case off:
+               break;
+       default:
+               logger_->info(buffer);
+               break;
+       }
+
+}
+
+void BaseLogger::setLogLevel(const std::string &level,
+               LOG_LEVEL_E defaultLevel) {
+       std::string logLevel = level;
+       std::transform(logLevel.begin(), logLevel.end(), logLevel.begin(),
+                       ::tolower);
+
+       if (logLevel == "trace") {
+               setLogLevel(trace);
+       } else if (logLevel == "debug") {
+               setLogLevel(debug);
+       } else if (logLevel == "info") {
+               setLogLevel(info);
+       } else if (logLevel == "warn") {
+               setLogLevel(warn);
+       } else if (logLevel == "error") {
+               setLogLevel(err);
+       } else if (logLevel == "critical") {
+               setLogLevel(critical);
+       } else if (logLevel == "off") {
+               setLogLevel(off);
+       } else {
+               setLogLevel(defaultLevel);
+       }
+}
+
+void BaseLogger::set_error_logger(std::shared_ptr<spdlog::logger> other) {
+       stderr_ = std::move(other);
+}
+

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/src/Configure.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/Configure.cpp b/libminifi/src/Configure.cpp
index dac8408..94e33a1 100644
--- a/libminifi/src/Configure.cpp
+++ b/libminifi/src/Configure.cpp
@@ -25,7 +25,6 @@ const char *Configure::nifi_flow_configuration_file = 
"nifi.flow.configuration.f
 const char *Configure::nifi_administrative_yield_duration = 
"nifi.administrative.yield.duration";
 const char *Configure::nifi_bored_yield_duration = "nifi.bored.yield.duration";
 const char *Configure::nifi_graceful_shutdown_seconds  = 
"nifi.graceful.shutdown.seconds";
-const char *Configure::nifi_log_level = "nifi.log.level";
 const char *Configure::nifi_server_name = "nifi.server.name";
 const char *Configure::nifi_server_port = "nifi.server.port";
 const char *Configure::nifi_server_report_interval= 
"nifi.server.report.interval";
@@ -39,6 +38,7 @@ const char *Configure::nifi_security_client_private_key = 
"nifi.security.client.
 const char *Configure::nifi_security_client_pass_phrase = 
"nifi.security.client.pass.phrase";
 const char *Configure::nifi_security_client_ca_certificate = 
"nifi.security.client.ca.certificate";
 
+
 //! Get the config value
 bool Configure::get(std::string key, std::string &value)
 {

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/src/FlowFileRecord.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/FlowFileRecord.cpp b/libminifi/src/FlowFileRecord.cpp
index 1d509f5..362602e 100644
--- a/libminifi/src/FlowFileRecord.cpp
+++ b/libminifi/src/FlowFileRecord.cpp
@@ -27,8 +27,9 @@
 #include <cstdio>
 
 #include "FlowFileRecord.h"
-#include "Relationship.h"
+
 #include "Logger.h"
+#include "Relationship.h"
 
 std::atomic<uint64_t> FlowFileRecord::_localFlowSeqNumber(0);
 

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/src/LogAppenders.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/LogAppenders.cpp b/libminifi/src/LogAppenders.cpp
new file mode 100644
index 0000000..c90588d
--- /dev/null
+++ b/libminifi/src/LogAppenders.cpp
@@ -0,0 +1,25 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "../include/LogAppenders.h"
+
+const char 
*OutputStreamAppender::nifi_log_output_stream_error_stderr="nifi.log.outputstream.appender.error.stderr";
+
+const char *RollingAppender::nifi_log_rolling_apender_file = 
"nifi.log.rolling.appender.file";
+const char *RollingAppender::nifi_log_rolling_appender_max_files = 
"nifi.log.rolling.appender.max.files";
+const char *RollingAppender::nifi_log_rolling_appender_max_file_size = 
"nifi.log.rolling.appender.max.file_size";

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/src/Logger.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/Logger.cpp b/libminifi/src/Logger.cpp
index fb3023d..e90667d 100644
--- a/libminifi/src/Logger.cpp
+++ b/libminifi/src/Logger.cpp
@@ -17,11 +17,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#include "../include/Logger.h"
+
 #include <vector>
 #include <queue>
 #include <map>
 
-#include "Logger.h"
 
-Logger *Logger::logger_(NULL);
+std::shared_ptr<Logger> Logger::singleton_logger_(nullptr);
 

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/src/Provenance.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/Provenance.cpp b/libminifi/src/Provenance.cpp
index ace3b45..ff4d8f5 100644
--- a/libminifi/src/Provenance.cpp
+++ b/libminifi/src/Provenance.cpp
@@ -23,8 +23,9 @@
 #include "io/DataStream.h"
 #include "io/Serializable.h"
 #include "Provenance.h"
-#include "Relationship.h"
+
 #include "Logger.h"
+#include "Relationship.h"
 #include "FlowController.h"
 
 //! DeSerialize

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/src/io/TLSSocket.cpp
----------------------------------------------------------------------
diff --git a/libminifi/src/io/TLSSocket.cpp b/libminifi/src/io/TLSSocket.cpp
index b38214e..b5fa596 100644
--- a/libminifi/src/io/TLSSocket.cpp
+++ b/libminifi/src/io/TLSSocket.cpp
@@ -28,7 +28,7 @@ std::atomic<TLSContext*> TLSContext::context_instance;
 std::mutex TLSContext::context_mutex;
 
 TLSContext::TLSContext() :
-               error_value(0), ctx(0), logger(Logger::getLogger()), 
configuration(
+               error_value(0), ctx(0), logger_(Logger::getLogger()), 
configuration(
                                Configure::getConfigure()) {
 
 }
@@ -56,7 +56,7 @@ short TLSContext::initialize() {
        method = TLSv1_2_client_method();
        ctx = SSL_CTX_new(method);
        if (ctx == NULL) {
-               logger->log_error("Could not create SSL context, error: %s.",
+               logger_->log_error("Could not create SSL context, error: %s.",
                                std::strerror(errno));
                error_value = TLS_ERROR_CONTEXT;
                return error_value;
@@ -71,7 +71,7 @@ short TLSContext::initialize() {
                                certificate)
                                && configuration->get(
                                                
Configure::nifi_security_client_private_key, privatekey))) {
-                       logger->log_error(
+                       logger_->log_error(
                                        "Certificate and Private Key PEM file 
not configured, error: %s.",
                                        std::strerror(errno));
                        error_value = TLS_ERROR_PEM_MISSING;
@@ -80,7 +80,7 @@ short TLSContext::initialize() {
                // load certificates and private key in PEM format
                if (SSL_CTX_use_certificate_file(ctx, certificate.c_str(),
                                SSL_FILETYPE_PEM) <= 0) {
-                       logger->log_error("Could not create load certificate, 
error : %s",
+                       logger_->log_error("Could not create load certificate, 
error : %s",
                                        std::strerror(errno));
                        error_value = TLS_ERROR_CERT_MISSING;
                        return error_value;
@@ -96,14 +96,14 @@ short TLSContext::initialize() {
                int retp = SSL_CTX_use_PrivateKey_file(ctx, privatekey.c_str(),
                                SSL_FILETYPE_PEM);
                if (retp != 1) {
-                       logger->log_error("Could not create load private key,%i 
on %s error : %s",
+                       logger_->log_error("Could not create load private 
key,%i on %s error : %s",
                                        
retp,privatekey.c_str(),std::strerror(errno));
                        error_value = TLS_ERROR_KEY_ERROR;
                        return error_value;
                }
                // verify private key
                if (!SSL_CTX_check_private_key(ctx)) {
-                       logger->log_error(
+                       logger_->log_error(
                                        "Private key does not match the public 
certificate, error : %s",
                                        std::strerror(errno));
                        error_value = TLS_ERROR_KEY_ERROR;
@@ -114,7 +114,7 @@ short TLSContext::initialize() {
                                caCertificate)) {
                        retp = SSL_CTX_load_verify_locations(ctx, 
caCertificate.c_str(), 0);
                        if (retp==0) {
-                               logger->log_error(
+                               logger_->log_error(
                                                "Can not load CA certificate, 
Exiting, error : %s",
                                                std::strerror(errno));
                                error_value = TLS_ERROR_CERT_ERROR;
@@ -122,7 +122,7 @@ short TLSContext::initialize() {
                        }
                }
 
-               logger->log_info("Load/Verify Client Certificate OK.");
+               logger_->log_info("Load/Verify Client Certificate OK.");
        }
        return 0;
 }

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/test/TestBase.h
----------------------------------------------------------------------
diff --git a/libminifi/test/TestBase.h b/libminifi/test/TestBase.h
index 4e7e73f..97c32e6 100644
--- a/libminifi/test/TestBase.h
+++ b/libminifi/test/TestBase.h
@@ -22,8 +22,8 @@
 #include <cstdlib>
 #include "ResourceClaim.h"
 #include "catch.hpp"
-#include "Logger.h"
 #include <vector>
+#include "Logger.h"
 
 
 class LogTestController {

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/test/unit/CRCTests.cpp
----------------------------------------------------------------------
diff --git a/libminifi/test/unit/CRCTests.cpp b/libminifi/test/unit/CRCTests.cpp
new file mode 100644
index 0000000..197b5be
--- /dev/null
+++ b/libminifi/test/unit/CRCTests.cpp
@@ -0,0 +1,81 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+#include <vector>
+#include "io/CRCStream.h"
+#include "io/DataStream.h"
+#include "../TestBase.h"
+
+
+TEST_CASE("Test CRC1", "[testcrc1]") {
+
+       BaseStream base;
+       CRCStream<BaseStream> test(&base);
+       test.writeData((uint8_t*)"cow",3);
+       REQUIRE(2580823964 == test.getCRC());
+       
+       
+}
+
+TEST_CASE("Test CRC2", "[testcrc2]") {
+
+       BaseStream base;
+       CRCStream<BaseStream> test(&base);
+       std::string fox = "the quick brown fox jumped over the brown fox";
+       std::vector<uint8_t> charvect(fox.begin(), fox.end()); 
+       test.writeData(charvect,charvect.size());
+       REQUIRE(1922388889 == test.getCRC());
+       
+       
+}
+
+
+TEST_CASE("Test CRC3", "[testcrc3]") {
+
+       BaseStream base;
+       CRCStream<BaseStream> test(&base);
+       uint64_t number=7;
+       test.write(number);
+       REQUIRE(4215687882 == test.getCRC());
+       
+       
+}
+
+
+TEST_CASE("Test CRC4", "[testcrc4]") {
+
+       BaseStream base;
+       CRCStream<BaseStream> test(&base);
+       uint32_t number=7;
+       test.write(number);
+       REQUIRE(3206564543 == test.getCRC());
+       
+       
+}
+
+TEST_CASE("Test CRC5", "[testcrc5]") {
+
+       BaseStream base;
+       CRCStream<BaseStream> test(&base);
+       uint16_t number=7;
+       test.write(number);
+       REQUIRE(3753740124 == test.getCRC());
+       
+       
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/test/unit/CRCTests.h
----------------------------------------------------------------------
diff --git a/libminifi/test/unit/CRCTests.h b/libminifi/test/unit/CRCTests.h
deleted file mode 100644
index de96eee..0000000
--- a/libminifi/test/unit/CRCTests.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <string>
-#include <vector>
-#include "io/CRCStream.h"
-#include "io/DataStream.h"
-TEST_CASE("Test CRC1", "[testcrc1]") {
-
-       BaseStream base;
-       CRCStream<BaseStream> test(&base);
-       test.writeData((uint8_t*)"cow",3);
-       REQUIRE(2580823964 == test.getCRC());
-       
-       
-}
-
-TEST_CASE("Test CRC2", "[testcrc2]") {
-
-       BaseStream base;
-       CRCStream<BaseStream> test(&base);
-       std::string fox = "the quick brown fox jumped over the brown fox";
-       std::vector<uint8_t> charvect(fox.begin(), fox.end()); 
-       test.writeData(charvect,charvect.size());
-       REQUIRE(1922388889 == test.getCRC());
-       
-       
-}
-
-
-TEST_CASE("Test CRC3", "[testcrc3]") {
-
-       BaseStream base;
-       CRCStream<BaseStream> test(&base);
-       uint64_t number=7;
-       test.write(number);
-       REQUIRE(4215687882 == test.getCRC());
-       
-       
-}
-
-
-TEST_CASE("Test CRC4", "[testcrc4]") {
-
-       BaseStream base;
-       CRCStream<BaseStream> test(&base);
-       uint32_t number=7;
-       test.write(number);
-       REQUIRE(3206564543 == test.getCRC());
-       
-       
-}
-
-TEST_CASE("Test CRC5", "[testcrc5]") {
-
-       BaseStream base;
-       CRCStream<BaseStream> test(&base);
-       uint16_t number=7;
-       test.write(number);
-       REQUIRE(3753740124 == test.getCRC());
-       
-       
-}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/test/unit/LoggerTests.cpp
----------------------------------------------------------------------
diff --git a/libminifi/test/unit/LoggerTests.cpp 
b/libminifi/test/unit/LoggerTests.cpp
new file mode 100644
index 0000000..8359037
--- /dev/null
+++ b/libminifi/test/unit/LoggerTests.cpp
@@ -0,0 +1,143 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+
+#include "../TestBase.h"
+#include "../../include/LogAppenders.h"
+
+bool contains(std::string stringA, std::string ending) {
+       return (ending.length() > 0 && stringA.find(ending) != 
std::string::npos);
+}
+
+TEST_CASE("Test log Levels", "[ttl1]") {
+       std::ostringstream oss;
+
+       std::unique_ptr<BaseLogger> outputLogger = 
std::unique_ptr<BaseLogger>(new OutputStreamAppender(oss,0));
+       std::shared_ptr<Logger> logger = Logger::getLogger();
+       logger->updateLogger(std::move(outputLogger));
+       logger->setLogLevel("trace");
+       logger->log_info("hello world");
+
+       REQUIRE( true == contains(oss.str(),"[minifi log -- 
OutputStreamAppender] [info] hello world"));
+}
+
+TEST_CASE("Test log Levels debug", "[ttl2]") {
+       std::ostringstream oss;
+
+       std::unique_ptr<BaseLogger> outputLogger = 
std::unique_ptr<BaseLogger>(new OutputStreamAppender(oss,0));
+       std::shared_ptr<Logger> logger = Logger::getLogger();
+       logger->updateLogger(std::move(outputLogger));
+       logger->setLogLevel("trace");
+       logger->log_debug("hello world");
+
+       REQUIRE( true == contains(oss.str(),"[minifi log -- 
OutputStreamAppender] [debug] hello world"));
+}
+
+TEST_CASE("Test log Levels trace", "[ttl3]") {
+       std::ostringstream oss;
+
+       std::unique_ptr<BaseLogger> outputLogger = 
std::unique_ptr<BaseLogger>(new OutputStreamAppender(oss,0));
+       std::shared_ptr<Logger> logger = Logger::getLogger();
+       logger->updateLogger(std::move(outputLogger));
+       logger->setLogLevel("trace");
+
+       logger->log_trace("hello world");
+
+       REQUIRE( true == contains(oss.str(),"[minifi log -- 
OutputStreamAppender] [trace] hello world"));
+}
+
+TEST_CASE("Test log Levels error", "[ttl4]") {
+       std::ostringstream oss;
+
+       std::unique_ptr<BaseLogger> outputLogger = 
std::unique_ptr<BaseLogger>(new OutputStreamAppender(oss,0));
+       std::shared_ptr<Logger> logger = Logger::getLogger();
+       logger->updateLogger(std::move(outputLogger));
+       logger->setLogLevel("trace");
+
+       logger->log_error("hello world");
+
+       REQUIRE( true == contains(oss.str(),"[minifi log -- 
OutputStreamAppender] [error] hello world"));
+}
+
+TEST_CASE("Test log Levels change", "[ttl5]") {
+       std::ostringstream oss;
+
+       std::unique_ptr<BaseLogger> outputLogger = 
std::unique_ptr<BaseLogger>(new OutputStreamAppender(oss,0));
+       std::shared_ptr<Logger> logger = Logger::getLogger();
+       logger->updateLogger(std::move(outputLogger));
+       logger->setLogLevel("trace");
+
+       logger->log_error("hello world");
+
+       REQUIRE( true == contains(oss.str(),"[minifi log -- 
OutputStreamAppender] [error] hello world"));
+       oss.str("");
+       oss.clear();
+       REQUIRE( 0 == oss.str().length() );
+       logger->setLogLevel("off");
+
+       logger->log_error("hello world");
+
+       REQUIRE( 0 == oss.str().length() );
+}
+
+TEST_CASE("Test log LevelsConfigured", "[ttl6]") {
+       std::ostringstream oss;
+
+       Configure *config = Configure::getConfigure();
+
+       config->set(BaseLogger::nifi_log_appender,"outputstreamappender");
+       
config->set(OutputStreamAppender::nifi_log_output_stream_error_stderr,"true");
+
+       std::shared_ptr<Logger> logger = Logger::getLogger();
+
+       auto oldrdbuf = std::cerr.rdbuf();
+       std::cerr.rdbuf(oss.rdbuf());
+
+       std::unique_ptr<BaseLogger> newLogger 
=LogInstance::getConfiguredLogger(config);
+
+       logger->updateLogger(std::move(newLogger));
+
+       logger->setLogLevel("trace");
+
+       // capture stderr
+       logger->log_error("hello world");
+
+       REQUIRE( true == contains(oss.str(),"[minifi log -- 
OutputStreamAppender] [error] hello world"));
+
+       std::cerr.rdbuf(oldrdbuf);
+
+       config->set(BaseLogger::nifi_log_appender,"nullappender");
+
+       newLogger =LogInstance::getConfiguredLogger(config);
+
+       logger->updateLogger(std::move(newLogger));
+
+       oss.str("");
+       oss.clear();
+       REQUIRE( 0 == oss.str().length() );
+
+       // should have nothing from the null appender
+       logger->log_info("hello world");
+       logger->log_debug("hello world");
+       logger->log_trace("hello world");
+//     logger->log_error("hello world");
+
+       REQUIRE( 0 == oss.str().length() );
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/test/unit/ProcessorTests.cpp
----------------------------------------------------------------------
diff --git a/libminifi/test/unit/ProcessorTests.cpp 
b/libminifi/test/unit/ProcessorTests.cpp
new file mode 100644
index 0000000..955d125
--- /dev/null
+++ b/libminifi/test/unit/ProcessorTests.cpp
@@ -0,0 +1,150 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <uuid/uuid.h>
+#include <fstream>
+#include "FlowController.h"
+#include "ProvenanceTestHelper.h"
+#include "../TestBase.h"
+#include "GetFile.h"
+
+
+TEST_CASE("Test Creation of GetFile", "[getfileCreate]"){
+       GetFile processor("processorname");
+       REQUIRE( processor.getName() == "processorname");
+}
+
+
+TEST_CASE("Test Find file", "[getfileCreate2]"){
+
+       TestController testController;
+
+       testController.enableDebug();
+
+       ProvenanceTestRepository repo;
+       TestFlowController controller(repo);
+       FlowControllerFactory::getFlowController( 
dynamic_cast<FlowController*>(&controller));
+
+       GetFile processor("getfileCreate2");
+
+       char format[] ="/tmp/gt.XXXXXX";
+       char *dir = testController.createTempDirectory(format);
+
+
+       uuid_t processoruuid;
+       REQUIRE( true == processor.getUUID(processoruuid) );
+
+       Connection connection("getfileCreate2Connection");
+       connection.setRelationship(Relationship("success","description"));
+
+       // link the connections so that we can test results at the end for this
+
+       connection.setSourceProcessor(&processor);
+
+
+       connection.setSourceProcessorUUID(processoruuid);
+       connection.setDestinationProcessorUUID(processoruuid);
+
+       processor.addConnection(&connection);
+       REQUIRE( dir != NULL );
+
+       ProcessContext context(&processor);
+       context.setProperty(GetFile::Directory,dir);
+       ProcessSession session(&context);
+
+
+       REQUIRE( processor.getName() == "getfileCreate2");
+
+       FlowFileRecord *record;
+       processor.setScheduledState(ScheduledState::RUNNING);
+       processor.onTrigger(&context,&session);
+
+       ProvenanceReporter *reporter = session.getProvenanceReporter();
+       std::set<ProvenanceEventRecord*> records = reporter->getEvents();
+
+       record = session.get();
+       REQUIRE( record== 0 );
+       REQUIRE( records.size() == 0 );
+
+       std::fstream file;
+       std::stringstream ss;
+       ss << dir << "/" << "tstFile.ext";
+       file.open(ss.str(),std::ios::out);
+       file << "tempFile";
+       file.close();
+
+       processor.incrementActiveTasks();
+       processor.setScheduledState(ScheduledState::RUNNING);
+       processor.onTrigger(&context,&session);
+       unlink(ss.str().c_str());
+       rmdir(dir);
+
+       reporter = session.getProvenanceReporter();
+
+       records = reporter->getEvents();
+
+       for(ProvenanceEventRecord *provEventRecord : records)
+       {
+               REQUIRE (provEventRecord->getComponentType() == 
processor.getName());
+       }
+       session.commit();
+
+       FlowFileRecord *ffr = session.get();
+
+       ffr->getResourceClaim()->decreaseFlowFileRecordOwnedCount();
+
+       delete ffr;
+
+       std::set<FlowFileRecord*> expiredFlows;
+
+       REQUIRE( 2 == repo.getRepoMap().size() );
+
+       for(auto  entry: repo.getRepoMap())
+       {
+               ProvenanceEventRecord newRecord;
+               
newRecord.DeSerialize((uint8_t*)entry.second.data(),entry.second.length());
+
+               bool found = false;
+               for ( auto provRec : records)
+               {
+                       if (provRec->getEventId() == newRecord.getEventId() )
+                       {
+                               REQUIRE( provRec->getEventId() == 
newRecord.getEventId());
+                               REQUIRE( provRec->getComponentId() == 
newRecord.getComponentId());
+                               REQUIRE( provRec->getComponentType() == 
newRecord.getComponentType());
+                               REQUIRE( provRec->getDetails() == 
newRecord.getDetails());
+                               REQUIRE( provRec->getEventDuration() == 
newRecord.getEventDuration());
+                               found = true;
+                               break;
+                       }
+               }
+               if (!found)
+               throw std::runtime_error("Did not find record");
+
+
+       }
+
+
+
+
+
+
+}
+
+
+
+

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/test/unit/ProcessorTests.h
----------------------------------------------------------------------
diff --git a/libminifi/test/unit/ProcessorTests.h 
b/libminifi/test/unit/ProcessorTests.h
deleted file mode 100644
index 0c17824..0000000
--- a/libminifi/test/unit/ProcessorTests.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <uuid/uuid.h>
-#include <fstream>
-#include "FlowController.h"
-#include "ProvenanceTests.h"
-#include "../TestBase.h"
-#include "GetFile.h"
-
-#ifndef PROCESSOR_TESTS
-#define PROCESSOR_TESTS
-
-TEST_CASE("Test Creation of GetFile", "[getfileCreate]"){
-       GetFile processor("processorname");
-       REQUIRE( processor.getName() == "processorname");
-}
-
-
-TEST_CASE("Test Find file", "[getfileCreate2]"){
-
-       TestController testController;
-
-       testController.enableDebug();
-
-       ProvenanceTestRepository repo;
-       TestFlowController controller(repo);
-       FlowControllerFactory::getFlowController( 
dynamic_cast<FlowController*>(&controller));
-
-       GetFile processor("getfileCreate2");
-
-       char format[] ="/tmp/gt.XXXXXX";
-       char *dir = testController.createTempDirectory(format);
-
-
-       uuid_t processoruuid;
-       REQUIRE( true == processor.getUUID(processoruuid) );
-
-       Connection connection("getfileCreate2Connection");
-       connection.setRelationship(Relationship("success","description"));
-
-       // link the connections so that we can test results at the end for this
-
-       connection.setSourceProcessor(&processor);
-
-
-       connection.setSourceProcessorUUID(processoruuid);
-       connection.setDestinationProcessorUUID(processoruuid);
-
-       processor.addConnection(&connection);
-       REQUIRE( dir != NULL );
-
-       ProcessContext context(&processor);
-       context.setProperty(GetFile::Directory,dir);
-       ProcessSession session(&context);
-
-
-       REQUIRE( processor.getName() == "getfileCreate2");
-
-       FlowFileRecord *record;
-       processor.setScheduledState(ScheduledState::RUNNING);
-       processor.onTrigger(&context,&session);
-
-       ProvenanceReporter *reporter = session.getProvenanceReporter();
-       std::set<ProvenanceEventRecord*> records = reporter->getEvents();
-
-       record = session.get();
-       REQUIRE( record== 0 );
-       REQUIRE( records.size() == 0 );
-
-       std::fstream file;
-       std::stringstream ss;
-       ss << dir << "/" << "tstFile.ext";
-       file.open(ss.str(),std::ios::out);
-       file << "tempFile";
-       file.close();
-
-       processor.incrementActiveTasks();
-       processor.setScheduledState(ScheduledState::RUNNING);
-       processor.onTrigger(&context,&session);
-       unlink(ss.str().c_str());
-       rmdir(dir);
-
-       reporter = session.getProvenanceReporter();
-
-       records = reporter->getEvents();
-
-       for(ProvenanceEventRecord *provEventRecord : records)
-       {
-               REQUIRE (provEventRecord->getComponentType() == 
processor.getName());
-       }
-       session.commit();
-
-       FlowFileRecord *ffr = session.get();
-
-       ffr->getResourceClaim()->decreaseFlowFileRecordOwnedCount();
-
-       delete ffr;
-
-       std::set<FlowFileRecord*> expiredFlows;
-
-       REQUIRE( 2 == repo.getRepoMap().size() );
-
-       for(auto  entry: repo.getRepoMap())
-       {
-               ProvenanceEventRecord newRecord;
-               
newRecord.DeSerialize((uint8_t*)entry.second.data(),entry.second.length());
-
-               bool found = false;
-               for ( auto provRec : records)
-               {
-                       if (provRec->getEventId() == newRecord.getEventId() )
-                       {
-                               REQUIRE( provRec->getEventId() == 
newRecord.getEventId());
-                               REQUIRE( provRec->getComponentId() == 
newRecord.getComponentId());
-                               REQUIRE( provRec->getComponentType() == 
newRecord.getComponentType());
-                               REQUIRE( provRec->getDetails() == 
newRecord.getDetails());
-                               REQUIRE( provRec->getEventDuration() == 
newRecord.getEventDuration());
-                               found = true;
-                               break;
-                       }
-               }
-               if (!found)
-               throw std::runtime_error("Did not find record");
-
-
-       }
-
-
-
-
-
-
-}
-
-
-
-#endif
-
-

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/test/unit/PropertyTests.cpp
----------------------------------------------------------------------
diff --git a/libminifi/test/unit/PropertyTests.cpp 
b/libminifi/test/unit/PropertyTests.cpp
new file mode 100644
index 0000000..e9f1c19
--- /dev/null
+++ b/libminifi/test/unit/PropertyTests.cpp
@@ -0,0 +1,103 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "utils/StringUtils.h"
+#include "../TestBase.h"
+#include "Property.h"
+
+TEST_CASE("Test Boolean Conversion", "[testboolConversion]") {
+
+       bool b;
+       REQUIRE(true == StringUtils::StringToBool("true",b));
+       REQUIRE(true == StringUtils::StringToBool("True",b));
+       REQUIRE(true == StringUtils::StringToBool("TRue",b));
+       REQUIRE(true == StringUtils::StringToBool("tRUE",b));
+
+       REQUIRE(false == StringUtils::StringToBool("FALSE",b));
+       REQUIRE(false == StringUtils::StringToBool("FALLSEY",b));
+       REQUIRE(false == StringUtils::StringToBool("FaLSE",b));
+       REQUIRE(false == StringUtils::StringToBool("false",b));
+
+}
+
+TEST_CASE("Test Trimmer Right", "[testTrims]") {
+
+       std::string test = "a quick brown fox jumped over the road\t\n";
+
+       REQUIRE(test.c_str()[test.length() - 1] == '\n');
+       REQUIRE(test.c_str()[test.length() - 2] == '\t');
+       test = StringUtils::trimRight(test);
+
+       REQUIRE(test.c_str()[test.length() - 1] == 'd');
+       REQUIRE(test.c_str()[test.length() - 2] == 'a');
+
+       test = "a quick brown fox jumped over the road\v\t";
+
+       REQUIRE(test.c_str()[test.length() - 1] == '\t');
+       REQUIRE(test.c_str()[test.length() - 2] == '\v');
+
+       test = StringUtils::trimRight(test);
+
+       REQUIRE(test.c_str()[test.length() - 1] == 'd');
+       REQUIRE(test.c_str()[test.length() - 2] == 'a');
+
+       test = "a quick brown fox jumped over the road \f";
+
+       REQUIRE(test.c_str()[test.length() - 1] == '\f');
+       REQUIRE(test.c_str()[test.length() - 2] == ' ');
+
+       test = StringUtils::trimRight(test);
+
+       REQUIRE(test.c_str()[test.length() - 1] == 'd');
+
+}
+
+TEST_CASE("Test Trimmer Left", "[testTrims]") {
+
+       std::string test = "\t\na quick brown fox jumped over the road\t\n";
+
+       REQUIRE(test.c_str()[0] == '\t');
+       REQUIRE(test.c_str()[1] == '\n');
+
+       test = StringUtils::trimLeft(test);
+
+       REQUIRE(test.c_str()[0] == 'a');
+       REQUIRE(test.c_str()[1] == ' ');
+
+       test = "\v\ta quick brown fox jumped over the road\v\t";
+
+       REQUIRE(test.c_str()[0] == '\v');
+       REQUIRE(test.c_str()[1] == '\t');
+
+       test = StringUtils::trimLeft(test);
+
+       REQUIRE(test.c_str()[0] == 'a');
+       REQUIRE(test.c_str()[1] == ' ');
+
+       test = " \fa quick brown fox jumped over the road \f";
+
+       REQUIRE(test.c_str()[0] == ' ');
+       REQUIRE(test.c_str()[1] == '\f');
+
+       test = StringUtils::trimLeft(test);
+
+       REQUIRE(test.c_str()[0] == 'a');
+       REQUIRE(test.c_str()[1] == ' ');
+
+}
+

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/f38859e4/libminifi/test/unit/PropertyTests.h
----------------------------------------------------------------------
diff --git a/libminifi/test/unit/PropertyTests.h 
b/libminifi/test/unit/PropertyTests.h
deleted file mode 100644
index 2633de9..0000000
--- a/libminifi/test/unit/PropertyTests.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef LIBMINIFI_TEST_UNIT_PROPERTYTESTS_H_
-#define LIBMINIFI_TEST_UNIT_PROPERTYTESTS_H_
-
-#include "utils/StringUtils.h"
-#include "../TestBase.h"
-#include "Property.h"
-
-TEST_CASE("Test Boolean Conversion", "[testboolConversion]") {
-
-       bool b;
-       REQUIRE(true == StringUtils::StringToBool("true",b));
-       REQUIRE(true == StringUtils::StringToBool("True",b));
-       REQUIRE(true == StringUtils::StringToBool("TRue",b));
-       REQUIRE(true == StringUtils::StringToBool("tRUE",b));
-
-       REQUIRE(false == StringUtils::StringToBool("FALSE",b));
-       REQUIRE(false == StringUtils::StringToBool("FALLSEY",b));
-       REQUIRE(false == StringUtils::StringToBool("FaLSE",b));
-       REQUIRE(false == StringUtils::StringToBool("false",b));
-
-}
-
-TEST_CASE("Test Trimmer Right", "[testTrims]") {
-
-       std::string test = "a quick brown fox jumped over the road\t\n";
-
-       REQUIRE(test.c_str()[test.length() - 1] == '\n');
-       REQUIRE(test.c_str()[test.length() - 2] == '\t');
-       test = StringUtils::trimRight(test);
-
-       REQUIRE(test.c_str()[test.length() - 1] == 'd');
-       REQUIRE(test.c_str()[test.length() - 2] == 'a');
-
-       test = "a quick brown fox jumped over the road\v\t";
-
-       REQUIRE(test.c_str()[test.length() - 1] == '\t');
-       REQUIRE(test.c_str()[test.length() - 2] == '\v');
-
-       test = StringUtils::trimRight(test);
-
-       REQUIRE(test.c_str()[test.length() - 1] == 'd');
-       REQUIRE(test.c_str()[test.length() - 2] == 'a');
-
-       test = "a quick brown fox jumped over the road \f";
-
-       REQUIRE(test.c_str()[test.length() - 1] == '\f');
-       REQUIRE(test.c_str()[test.length() - 2] == ' ');
-
-       test = StringUtils::trimRight(test);
-
-       REQUIRE(test.c_str()[test.length() - 1] == 'd');
-
-}
-
-TEST_CASE("Test Trimmer Left", "[testTrims]") {
-
-       std::string test = "\t\na quick brown fox jumped over the road\t\n";
-
-       REQUIRE(test.c_str()[0] == '\t');
-       REQUIRE(test.c_str()[1] == '\n');
-
-       test = StringUtils::trimLeft(test);
-
-       REQUIRE(test.c_str()[0] == 'a');
-       REQUIRE(test.c_str()[1] == ' ');
-
-       test = "\v\ta quick brown fox jumped over the road\v\t";
-
-       REQUIRE(test.c_str()[0] == '\v');
-       REQUIRE(test.c_str()[1] == '\t');
-
-       test = StringUtils::trimLeft(test);
-
-       REQUIRE(test.c_str()[0] == 'a');
-       REQUIRE(test.c_str()[1] == ' ');
-
-       test = " \fa quick brown fox jumped over the road \f";
-
-       REQUIRE(test.c_str()[0] == ' ');
-       REQUIRE(test.c_str()[1] == '\f');
-
-       test = StringUtils::trimLeft(test);
-
-       REQUIRE(test.c_str()[0] == 'a');
-       REQUIRE(test.c_str()[1] == ' ');
-
-}
-
-#endif /* LIBMINIFI_TEST_UNIT_PROPERTYTESTS_H_ */

Reply via email to