You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ch...@apache.org on 2013/04/26 23:38:07 UTC

svn commit: r1476409 - in /qpid/trunk/qpid/cpp: include/qpid/log/ src/qpid/broker/ src/qpid/log/ src/tests/

Author: chug
Date: Fri Apr 26 21:38:07 2013
New Revision: 1476409

URL: http://svn.apache.org/r1476409
Log:
QPID-4651: C++ Broker add --log-disable option
Reviewed at https://reviews.apache.org/r/10799/


Modified:
    qpid/trunk/qpid/cpp/include/qpid/log/Options.h
    qpid/trunk/qpid/cpp/include/qpid/log/Selector.h
    qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp
    qpid/trunk/qpid/cpp/src/qpid/log/Logger.cpp
    qpid/trunk/qpid/cpp/src/qpid/log/Options.cpp
    qpid/trunk/qpid/cpp/src/qpid/log/Selector.cpp
    qpid/trunk/qpid/cpp/src/tests/BrokerFixture.h
    qpid/trunk/qpid/cpp/src/tests/dynamic_log_level_test
    qpid/trunk/qpid/cpp/src/tests/logging.cpp

Modified: qpid/trunk/qpid/cpp/include/qpid/log/Options.h
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/include/qpid/log/Options.h?rev=1476409&r1=1476408&r2=1476409&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/include/qpid/log/Options.h (original)
+++ qpid/trunk/qpid/cpp/include/qpid/log/Options.h Fri Apr 26 21:38:07 2013
@@ -39,6 +39,7 @@ struct Options : public qpid::Options {
     std::string argv0;
     std::string name;
     std::vector<std::string> selectors;
+    std::vector<std::string> deselectors;
     bool time, level, thread, source, function, hiresTs, category;
     bool trace;
     std::string prefix;

Modified: qpid/trunk/qpid/cpp/include/qpid/log/Selector.h
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/include/qpid/log/Selector.h?rev=1476409&r1=1476408&r2=1476409&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/include/qpid/log/Selector.h (original)
+++ qpid/trunk/qpid/cpp/include/qpid/log/Selector.h Fri Apr 26 21:38:07 2013
@@ -28,6 +28,22 @@ namespace log {
 struct Options;
 
 /**
+ * SelectorElement parses a cli/mgmt enable/disable entry into usable fields
+ * where cliEntry = [!]LEVEL[+-][:PATTERN]
+ */
+struct SelectorElement {
+    SelectorElement(const std::string cliEntry);
+    std::string levelStr;
+    std::string patternStr;
+    Level level;
+    Category category;
+    bool isDisable;
+    bool isCategory;
+    bool isLevelAndAbove;
+    bool isLevelAndBelow;
+};
+
+/**
  * A selector identifies the set of log messages to enable.
  *
  * Thread object unsafe, pass-by-value type.
@@ -35,56 +51,45 @@ struct Options;
 class Selector {
   public:
     /** Empty selector selects nothing */
-    Selector() {
-        reset();
-    }
+    Selector();
 
     /** Set selector from Options */
     QPID_COMMON_EXTERN Selector(const Options&);
 
     /** Equavlient to: Selector s; s.enable(l, s) */
-    Selector(Level l, const std::string& s=std::string()) {
-        reset();
-        enable(l,s);
-    }
-
-    Selector(const std::string& enableStr) {
-        reset();
-        enable(enableStr);
-    }
+    Selector(Level l, const std::string& s=std::string());
 
-    /**
-     * Enable messages with level in levels where the file
-     * name contains substring. Empty string matches all.
-     */
-    void enable(Level level, const std::string& substring=std::string()) {
-        substrings[level].push_back(substring);
-    }
+    /** Selector from string */
+    Selector(const std::string& selector);
+
+    /** push option settings into runtime lookup structs */
+    QPID_COMMON_EXTERN void enable(const std::string& enableStr);
+    QPID_COMMON_EXTERN void disable(const std::string& disableStr);
 
     /**
-     * Enable messages at this level for this category
+     * Enable/disable messages with level in levels where the file
+     * name contains substring. Empty string matches all.
      */
-    void enable(Level level, Category category) {
-        catFlags[level][category] = true;
-    }
-
-    /** Enable based on a 'level[+]:file' string */
-    QPID_COMMON_EXTERN void enable(const std::string& enableStr);
+    void enable(Level level, const std::string& substring=std::string());
+    void disable(Level level, const std::string& substring=std::string());
 
-    /** True if level is enabled for file. */
+    /** Tests to determine if function names are in enable/disable tables */
     QPID_COMMON_EXTERN bool isEnabled(Level level, const char* function);
-    QPID_COMMON_EXTERN bool isEnabled(Level level, const char* function, Category category);
+    QPID_COMMON_EXTERN bool isDisabled(Level level, const char* function);
 
-    /** Reset the category enable flags */
-    QPID_COMMON_EXTERN void reset() {
-        for (int lt = 0; lt < LevelTraits::COUNT; ++lt)
-            for (int ct = 0; ct < CategoryTraits::COUNT; ++ct)
-                catFlags[lt][ct] = false;
-    }
+    /** Test to determine if log Statement is enabled */
+    QPID_COMMON_EXTERN bool isEnabled(Level level, const char* function, Category category);
 
   private:
-    std::vector<std::string> substrings[LevelTraits::COUNT];
-    bool catFlags[LevelTraits::COUNT][CategoryTraits::COUNT];
+    typedef std::vector<std::string> FunctionNameTable [LevelTraits::COUNT];
+    FunctionNameTable enabledFunctions;   // log function names explicitly enabled
+    FunctionNameTable disabledFunctions;  // log function names explicitly disabled
+    bool enableFlags[LevelTraits::COUNT][CategoryTraits::COUNT];
+    bool disableFlags[LevelTraits::COUNT][CategoryTraits::COUNT];
+
+    bool lookupFuncName(Level level, const char* function, FunctionNameTable& table);
+    /** Reset the category enable flags */
+    QPID_COMMON_EXTERN void reset();
 };
 
 

Modified: qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp?rev=1476409&r1=1476408&r2=1476409&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp Fri Apr 26 21:38:07 2013
@@ -1018,10 +1018,16 @@ void Broker::setLogLevel(const std::stri
 std::string Broker::getLogLevel()
 {
     std::string level;
+    std::string sep("");
     const std::vector<std::string>& selectors = qpid::log::Logger::instance().getOptions().selectors;
     for (std::vector<std::string>::const_iterator i = selectors.begin(); i != selectors.end(); ++i) {
-        if (i != selectors.begin()) level += std::string(",");
-        level += *i;
+        level += sep + *i;
+        sep = ",";
+    }
+    const std::vector<std::string>& disselectors = qpid::log::Logger::instance().getOptions().deselectors;
+    for (std::vector<std::string>::const_iterator i = disselectors.begin(); i != disselectors.end(); ++i) {
+        level += sep + "!" + *i;
+        sep = ",";
     }
     return level;
 }

Modified: qpid/trunk/qpid/cpp/src/qpid/log/Logger.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/log/Logger.cpp?rev=1476409&r1=1476408&r2=1476409&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/log/Logger.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/log/Logger.cpp Fri Apr 26 21:38:07 2013
@@ -172,6 +172,7 @@ void Logger::configure(const Options& op
 
 void Logger::reconfigure(const std::vector<std::string>& selectors) {
     options.selectors = selectors;
+    options.deselectors.clear();
     select(Selector(options));
 }
 

Modified: qpid/trunk/qpid/cpp/src/qpid/log/Options.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/log/Options.cpp?rev=1476409&r1=1476408&r2=1476409&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/log/Options.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/log/Options.cpp Fri Apr 26 21:38:07 2013
@@ -59,16 +59,33 @@ Options::Options(const std::string& argv
         ("trace,t", optValue(trace), "Enables all logging" )
         ("log-enable", optValue(selectors, "RULE"),
          ("Enables logging for selected levels and components. "
-          "RULE is in the form 'LEVEL[+][:PATTERN]' "
+          "RULE is in the form 'LEVEL[+-][:PATTERN]'\n"
           "LEVEL is one of: \n\t "+levels.str()+"\n"
-          "PATTERN is a function name or a catogory: \n\t "+categories.str()+"\n"
+          "PATTERN is a logging category name, or a namespace-qualified "
+          "function name or name fragment. "
+          "Logging category names are: \n\t "+categories.str()+"\n"
           "For example:\n"
-          "\t'--log-enable warning+' "
+          "\t'--log-enable warning+'\n"
           "logs all warning, error and critical messages.\n"
-          "\t'--log-enable trace+:Broker' "
+          "\t'--log-enable trace+:Broker'\n"
           "logs all category 'Broker' messages.\n"
-          "\t'--log-enable debug:framing' "
-          "logs debug messages from the framing namespace. "
+          "\t'--log-enable debug:framing'\n"
+          "logs debug messages from all functions with 'framing' in the namespace or function name.\n"
+          "This option can be used multiple times").c_str())
+        ("log-disable", optValue(deselectors, "RULE"),
+         ("Disables logging for selected levels and components. "
+          "RULE is in the form 'LEVEL[+-][:PATTERN]'\n"
+          "LEVEL is one of: \n\t "+levels.str()+"\n"
+          "PATTERN is a logging category name, or a namespace-qualified "
+          "function name or name fragment. "
+          "Logging category names are: \n\t "+categories.str()+"\n"
+          "For example:\n"
+          "\t'--log-disable warning-'\n"
+          "disables logging all warning, notice, info, debug, and trace messages.\n"
+          "\t'--log-disable trace:Broker'\n"
+          "disables all category 'Broker' trace messages.\n"
+          "\t'--log-disable debug-:qmf::'\n"
+          "disables logging debug and trace messages from all functions with 'qmf::' in the namespace.\n"
           "This option can be used multiple times").c_str())
         ("log-time", optValue(time, "yes|no"), "Include time in log messages")
         ("log-level", optValue(level,"yes|no"), "Include severity level in log messages")
@@ -77,7 +94,7 @@ Options::Options(const std::string& argv
         ("log-function", optValue(function,"yes|no"), "Include function signature in log messages")
         ("log-hires-timestamp", optValue(hiresTs,"yes|no"), "Use hi-resolution timestamps in log messages")
         ("log-category", optValue(category,"yes|no"), "Include category in log messages")
-        ("log-prefix", optValue(prefix,"STRING"), "Prefix to append to all log messages")
+        ("log-prefix", optValue(prefix,"STRING"), "Prefix to prepend to all log messages")
         ;
     add(*sinkOptions);
 }
@@ -87,6 +104,7 @@ Options::Options(const Options &o) :
     argv0(o.argv0),
     name(o.name),
     selectors(o.selectors),
+    deselectors(o.deselectors),
     time(o.time),
     level(o.level),
     thread(o.thread),
@@ -106,6 +124,7 @@ Options& Options::operator=(const Option
         argv0 = x.argv0;
         name = x.name;
         selectors = x.selectors;
+        deselectors = x.deselectors;
         time = x.time;
         level= x.level;
         thread = x.thread;

Modified: qpid/trunk/qpid/cpp/src/qpid/log/Selector.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/log/Selector.cpp?rev=1476409&r1=1476408&r2=1476409&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/log/Selector.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/log/Selector.cpp Fri Apr 26 21:38:07 2013
@@ -27,59 +27,209 @@ namespace log {
 
 using namespace std;
 
-void Selector::enable(const string& enableStr) {
-    string level, pattern;
-    size_t c=enableStr.find(':');
+const char LOG_SYMBOL_DISABLE  ('!');
+const char LOG_SYMBOL_SEPERATOR(':');
+const char LOG_SYMBOL_AND_ABOVE('+');
+const char LOG_SYMBOL_AND_BELOW('-');
+
+//
+// Parse an enable or disable entry into usable fields.
+// Throws if 'level' field is not recognized.
+//
+SelectorElement::SelectorElement(const std::string cliEntry) :
+    level(qpid::log::debug),
+    category(qpid::log::unspecified),
+    isDisable(false),
+    isCategory(false),
+    isLevelAndAbove(false),
+    isLevelAndBelow(false)
+{
+    if (cliEntry.empty())
+        return;
+    std::string working(cliEntry);
+    if (LOG_SYMBOL_DISABLE == working[0]) {
+        isDisable = true;
+        working = working.substr(1);
+    }
+    size_t c=working.find(LOG_SYMBOL_SEPERATOR);
     if (c==string::npos) {
-        level=enableStr;
+        levelStr=working;
+    } else {
+        levelStr=working.substr(0,c);
+        patternStr=working.substr(c+1);
     }
-    else {
-        level=enableStr.substr(0,c);
-        pattern=enableStr.substr(c+1);
-    }
-    bool isCat = CategoryTraits::isCategory(pattern);
-    if (!level.empty() && level[level.size()-1]=='+') {
-        for (int i =  LevelTraits::level(level.substr(0,level.size()-1));
-             i < LevelTraits::COUNT;
-             ++i) {
-            if (isCat) {
-                enable(Level(i), CategoryTraits::category(pattern));
-            } else {
-                enable(Level(i), pattern);
-            }
+    if (!levelStr.empty()) {
+        if (levelStr[levelStr.size()-1]==LOG_SYMBOL_AND_ABOVE) {
+            isLevelAndAbove = true;
+            levelStr = levelStr.substr(0, levelStr.size()-1);
+        } else if (levelStr[levelStr.size()-1]==LOG_SYMBOL_AND_BELOW) {
+            isLevelAndBelow = true;
+            levelStr = levelStr.substr(0, levelStr.size()-1);
         }
     }
-    else {
-        if (isCat) {
-            enable(LevelTraits::level(level), CategoryTraits::category(pattern));
-        } else {
-            enable(LevelTraits::level(level), pattern);
-        }
+    level = LevelTraits::level(levelStr);  // throws if bad level name
+    isCategory = CategoryTraits::isCategory(patternStr);
+    if (isCategory) {
+        category = CategoryTraits::category(patternStr);
     }
 }
 
+// Empty selector
+Selector::Selector() {
+    reset();
+}
+
+
+// Selector from options
 Selector::Selector(const Options& opt){
     reset();
     for_each(opt.selectors.begin(), opt.selectors.end(),
              boost::bind(&Selector::enable, this, _1));
+    for_each(opt.deselectors.begin(), opt.deselectors.end(),
+             boost::bind(&Selector::disable, this, _1));
 }
 
-bool Selector::isEnabled(Level level, const char* function) {
+
+// Selector from single level
+Selector::Selector(Level l, const std::string& s) {
+    reset();
+    enable(l, s);
+}
+
+
+// Selector from single enable
+Selector::Selector(const std::string& selector) {
+    reset();
+    enable(selector);
+}
+
+
+/**
+ * Process a single CLI --log-enable option
+ */
+void Selector::enable(const string& enableStr) {
+    if (enableStr.empty())
+        return;
+    SelectorElement se(enableStr);
+    if (se.isDisable) {
+        // Disable statements are allowed in an enable string as a convenient
+        // way to process management strings that have enable/disable mixed.
+        disable(enableStr);
+    } else if (se.isLevelAndAbove) {
+        for (int lvl = se.level; lvl < LevelTraits::COUNT; ++lvl) {
+            if (se.isCategory) {
+                enableFlags[lvl][se.category] = true;
+            } else {
+                enable(Level(lvl), se.patternStr);
+            }
+        }
+    } else if (se.isLevelAndBelow) {
+        for (int lvl = se.level; lvl >= 0; --lvl) {
+            if (se.isCategory) {
+                enableFlags[lvl][se.category] = true;
+            } else {
+                enable(Level(lvl), se.patternStr);
+            }
+        }
+    } else {
+        if (se.isCategory) {
+            enableFlags[se.level][se.category] = true;
+        } else {
+            enable(se.level, se.patternStr);
+        }
+    }
+}
+
+void Selector::disable(const string& disableStr) {
+    if (disableStr.empty())
+        return;
+    SelectorElement se(disableStr);
+    if (se.isLevelAndAbove) {
+        for (int lvl = se.level; lvl < LevelTraits::COUNT; ++lvl) {
+            if (se.isCategory) {
+                disableFlags[lvl][se.category] = true;
+            } else {
+                disable(Level(lvl), se.patternStr);
+            }
+        }
+    } else if (se.isLevelAndBelow) {
+        for (int lvl = se.level; lvl >= 0; --lvl) {
+            if (se.isCategory) {
+                disableFlags[lvl][se.category] = true;
+            } else {
+                disable(Level(lvl), se.patternStr);
+            }
+        }
+    } else {
+        if (se.isCategory) {
+            disableFlags[se.level][se.category] = true;
+        } else {
+            disable(se.level, se.patternStr);
+        }
+    }
+}
+
+
+/**
+* Enable/disable messages with level in levels where the file
+* name contains substring.
+*/
+void Selector::enable(Level level, const std::string& substring) {
+    enabledFunctions[level].push_back(substring);
+}
+
+
+void Selector::disable(Level level, const std::string& substring) {
+    disabledFunctions[level].push_back(substring);
+}
+
+
+void Selector::reset() {
+    // Initialize fields in a Selector that are not automatically set
+    for (int lt = 0; lt < LevelTraits::COUNT; ++lt)
+        for (int ct = 0; ct < CategoryTraits::COUNT; ++ct)
+            enableFlags[lt][ct] = disableFlags[lt][ct] = false;
+}
+
+
+bool Selector::lookupFuncName(Level level, const char* function, FunctionNameTable& table) {
     const char* functionEnd = function+::strlen(function);
-    for (std::vector<std::string>::iterator i=substrings[level].begin();
-         i != substrings[level].end();
+    for (std::vector<std::string>::iterator i=table[level].begin();
+         i != table[level].end();
          ++i)
-        {
-            if (std::search(function, functionEnd, i->begin(), i->end()) != functionEnd)
-                return true;
-        }
+    {
+        if (std::search(function, functionEnd, i->begin(), i->end()) != functionEnd)
+            return true;
+    }
     return false;
 }
 
+
+bool Selector::isEnabled(Level level, const char* function) {
+    return lookupFuncName(level, function, enabledFunctions);
+}
+
+bool Selector::isDisabled(Level level, const char* function) {
+    return lookupFuncName(level, function, disabledFunctions);
+}
+
+//
+// isEnabled
+//
+// Determines if all the fields in this Selector enable or disable a
+// level/function/category set from an actual QPID_LOG Statement.
+//
 bool Selector::isEnabled(Level level, const char* function, Category category) {
-    if (catFlags[level][category])
-        return true;
-    return isEnabled(level, function);
+    if (isDisabled(level, function))
+        return false;                   // Disabled by function name
+    if (disableFlags[level][category])
+        return false;                   // Disabled by category name
+    if (isEnabled(level, function))
+        return true;                    // Enabled by function name
+    if (enableFlags[level][category])
+        return true;                    // Enabled by category name
+    else
+        return false;                   // Unspecified defaults to disabled
 }
 
 }} // namespace qpid::log

Modified: qpid/trunk/qpid/cpp/src/tests/BrokerFixture.h
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/BrokerFixture.h?rev=1476409&r1=1476408&r2=1476409&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/BrokerFixture.h (original)
+++ qpid/trunk/qpid/cpp/src/tests/BrokerFixture.h Fri Apr 26 21:38:07 2013
@@ -51,6 +51,7 @@ struct  BrokerFixture : private boost::n
         if (!::getenv("QPID_LOG_ENABLE") && !::getenv("QPID_TRACE")) {
             qpid::log::Options logOpts;
             logOpts.selectors.clear();
+            logOpts.deselectors.clear();
             logOpts.selectors.push_back("error+");
             qpid::log::Logger::instance().configure(logOpts);
         }

Modified: qpid/trunk/qpid/cpp/src/tests/dynamic_log_level_test
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/dynamic_log_level_test?rev=1476409&r1=1476408&r2=1476409&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/dynamic_log_level_test (original)
+++ qpid/trunk/qpid/cpp/src/tests/dynamic_log_level_test Fri Apr 26 21:38:07 2013
@@ -35,23 +35,56 @@ error() { 
     exit 1;
 }
 
+checklog() {
+    if [[ $(grep echo $LOG_FILE | wc -l) -ne $1 ]]; then 
+        cat $LOG_FILE
+        error "Log contents not as expected - " $2
+    fi
+}
+
 rm -rf $LOG_FILE
 PORT=$($QPIDD_EXEC --auth=no --no-module-dir --daemon --port=0 --log-to-file $LOG_FILE) || error "Could not start broker"
 
 echo Broker for log level test started on $PORT, pid is $($QPIDD_EXEC --no-module-dir --check --port $PORT)
 
+# Set level to notice+ and send an echo request
+# The 'echo' in the log is hidden since it is at debug level.
 $srcdir/qpid-ctrl -b localhost:$PORT setLogLevel level='notice+' > /dev/null
 $srcdir/qpid-ctrl -b localhost:$PORT echo sequence=1 body=HIDDEN > /dev/null
+checklog 0 "Step 1 Expected no echo log entries"
+
+# Next, enable all Broker logs at debug and higher levels and send another echo
+# This 'echo' should be in the log.
 $srcdir/qpid-ctrl -b localhost:$PORT setLogLevel level='debug+:Broker' > /dev/null
 $srcdir/qpid-ctrl -b localhost:$PORT echo sequence=2 body=VISIBLE > /dev/null
-$srcdir/qpid-ctrl -b localhost:$PORT setLogLevel level='notice+' > /dev/null
+checklog 1 "Step 2 Expected one echo log entry"
 
-#check log includes debug statement for last echo, but not the first
-if [[ $(grep echo $LOG_FILE | wc -l) -ne 1 ]]; then 
-   cat $LOG_FILE
-   error "Log contents not as expected"
-else
-  rm -rf $LOG_FILE
-  echo OK
+# Now turn on Broker debug messages but specifically disable ManagementMethod logs
+# The 'echo' should be hidden.
+$srcdir/qpid-ctrl -b localhost:$PORT setLogLevel level='debug+:Broker !debug+:broker::Broker::ManagementMethod' > /dev/null
+$srcdir/qpid-ctrl -b localhost:$PORT echo sequence=3 body=HIDDEN > /dev/null
+checklog 1 "Step 3 Expected one echo log entry"
+
+# Verify that the management get returns what was just set
+$srcdir/qpid-ctrl -b localhost:$PORT getLogLevel > dynamic_log_level.tmp
+if [[ $(grep 'level=debug+:Broker,!debug+:broker::Broker::ManagementMethod' dynamic_log_level.tmp | wc -l) -ne 1 ]]; then
+    error "Step 4 getLogLevel returned unexpected value: " `cat dynamic_log_level.tmp`
 fi
+rm -rf dynamic_log_level.tmp
+
+cleanup
+
+# Start another broker with --log-disable settings and make sure the management string receives them
+rm -rf $LOG_FILE
+PORT=$($QPIDD_EXEC --auth=no --no-module-dir --daemon --port=0 --log-to-file $LOG_FILE --log-enable debug:foo --log-disable debug:bar) || error "Could not start broker"
+echo Broker for log level test started on $PORT, pid is $($QPIDD_EXEC --no-module-dir --check --port $PORT)
+
+$srcdir/qpid-ctrl -b localhost:$PORT getLogLevel > dynamic_log_level.tmp
+if [[ $(grep 'level=debug:foo,!debug:bar' dynamic_log_level.tmp | wc -l) -ne 1 ]]; then
+    error "Step 5 getLogLevel returned unexpected value: " `cat dynamic_log_level.tmp`
+fi
+rm -rf dynamic_log_level.tmp
+
+rm -rf $LOG_FILE
+echo OK
 

Modified: qpid/trunk/qpid/cpp/src/tests/logging.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/logging.cpp?rev=1476409&r1=1476408&r2=1476409&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/logging.cpp (original)
+++ qpid/trunk/qpid/cpp/src/tests/logging.cpp Fri Apr 26 21:38:07 2013
@@ -85,6 +85,17 @@ QPID_AUTO_TEST_CASE(testSelector_enable)
     BOOST_CHECK(s.isEnabled(critical, "oops"));
 }
 
+QPID_AUTO_TEST_CASE(testSelector_disable) {
+    Selector s;
+    // Simple enable/disable
+    s.enable(trace,"foo");
+    BOOST_CHECK(s.isEnabled(trace,"foo"));
+    BOOST_CHECK(!s.isDisabled(trace,"foo"));
+    s.disable(trace,"foo");
+    BOOST_CHECK(s.isEnabled(trace,"foo"));
+    BOOST_CHECK(s.isDisabled(trace,"foo"));
+}
+
 QPID_AUTO_TEST_CASE(testStatementEnabled) {
     // Verify that the singleton enables and disables static
     // log statements.
@@ -271,6 +282,9 @@ QPID_AUTO_TEST_CASE(testOptionsParse) {
         "--log-enable", "error+:foo",
         "--log-enable", "debug:bar",
         "--log-enable", "info",
+        "--log-disable", "error+:foo",
+        "--log-disable", "debug:bar",
+        "--log-disable", "info",
         "--log-to-stderr", "no",
         "--log-to-file", "logout",
         "--log-level", "yes",
@@ -288,6 +302,7 @@ QPID_AUTO_TEST_CASE(testOptionsParse) {
     sinks = *opts.sinkOptions;
     vector<string> expect=list_of("error+:foo")("debug:bar")("info");
     BOOST_CHECK_EQUAL(expect, opts.selectors);
+    BOOST_CHECK_EQUAL(expect, opts.deselectors);
     BOOST_CHECK(!sinks.logToStderr);
     BOOST_CHECK(!sinks.logToStdout);
     BOOST_CHECK(sinks.logFile == "logout");
@@ -333,6 +348,64 @@ QPID_AUTO_TEST_CASE(testSelectorFromOpti
     BOOST_CHECK(s.isEnabled(critical, "foo"));
 }
 
+QPID_AUTO_TEST_CASE(testDeselectorFromOptions) {
+    const char* argv[]={
+        0,
+        "--log-disable", "error-:foo",
+        "--log-disable", "debug:bar",
+        "--log-disable", "info"
+    };
+    qpid::log::Options opts("");
+    opts.parse(ARGC(argv), const_cast<char**>(argv));
+    vector<string> expect=list_of("error-:foo")("debug:bar")("info");
+    BOOST_CHECK_EQUAL(expect, opts.deselectors);
+    Selector s(opts);
+    BOOST_CHECK(!s.isDisabled(warning, "x"));
+    BOOST_CHECK(!s.isDisabled(debug, "x"));
+    BOOST_CHECK(s.isDisabled(debug, "bar"));
+    BOOST_CHECK(s.isDisabled(trace, "foo"));
+    BOOST_CHECK(s.isDisabled(debug, "foo"));
+    BOOST_CHECK(s.isDisabled(info, "foo"));
+    BOOST_CHECK(s.isDisabled(notice, "foo"));
+    BOOST_CHECK(s.isDisabled(warning, "foo"));
+    BOOST_CHECK(s.isDisabled(error, "foo"));
+    BOOST_CHECK(!s.isDisabled(critical, "foo"));
+}
+
+QPID_AUTO_TEST_CASE(testMultiConflictingSelectorFromOptions) {
+    const char* argv[]={
+        0,
+        "--log-enable",  "trace+:foo",
+        "--log-disable", "error-:foo",
+        "--log-enable",  "debug:bar",
+        "--log-disable", "debug:bar",
+        "--log-enable",  "info",
+        "--log-disable", "info",
+        "--log-enable",  "debug+:Model",
+        "--log-disable", "info-:Model"
+    };
+    qpid::log::Options opts("");
+    opts.parse(ARGC(argv), const_cast<char**>(argv));
+    Selector s(opts);
+    BOOST_CHECK(!s.isEnabled(warning, "x", log::broker));
+    BOOST_CHECK(!s.isEnabled(debug, "x", log::broker));
+    BOOST_CHECK(!s.isEnabled(trace, "foo", log::broker));
+    BOOST_CHECK(!s.isEnabled(debug, "foo", log::broker));
+    BOOST_CHECK(!s.isEnabled(info, "foo", log::broker));
+    BOOST_CHECK(!s.isEnabled(notice, "foo", log::broker));
+    BOOST_CHECK(!s.isEnabled(warning, "foo", log::broker));
+    BOOST_CHECK(!s.isEnabled(error, "foo", log::broker));
+    BOOST_CHECK(s.isEnabled(critical, "foo", log::broker));
+    BOOST_CHECK(!s.isEnabled(debug, "bar", log::model));
+    BOOST_CHECK(!s.isEnabled(trace, "zaz", log::model));
+    BOOST_CHECK(!s.isEnabled(debug, "zaz", log::model));
+    BOOST_CHECK(!s.isEnabled(info, "zaz", log::model));
+    BOOST_CHECK(s.isEnabled(notice, "zaz", log::model));
+    BOOST_CHECK(s.isEnabled(warning, "zaz", log::model));
+    BOOST_CHECK(s.isEnabled(error, "zaz", log::model));
+    BOOST_CHECK(s.isEnabled(critical, "zaz", log::model));
+}
+
 QPID_AUTO_TEST_CASE(testLoggerStateure) {
     Logger& l=Logger::instance();
     ScopedSuppressLogging ls(l);
@@ -385,6 +458,55 @@ QPID_AUTO_TEST_CASE(testQuoteNonPrintabl
     unlink("logging.tmp");
 }
 
+QPID_AUTO_TEST_CASE(testSelectorElements) {
+    SelectorElement s("debug");
+    BOOST_CHECK_EQUAL(s.levelStr, "debug");
+    BOOST_CHECK_EQUAL(s.patternStr, "");
+    BOOST_CHECK_EQUAL(s.level, debug);
+    BOOST_CHECK(!s.isDisable);
+    BOOST_CHECK(!s.isCategory);
+    BOOST_CHECK(!s.isLevelAndAbove);
+    BOOST_CHECK(!s.isLevelAndBelow);
+
+    SelectorElement t("debug:Broker");
+    BOOST_CHECK_EQUAL(t.levelStr, "debug");
+    BOOST_CHECK_EQUAL(t.patternStr, "Broker");
+    BOOST_CHECK_EQUAL(t.level, debug);
+    BOOST_CHECK_EQUAL(t.category, broker);
+    BOOST_CHECK(!t.isDisable);
+    BOOST_CHECK(t.isCategory);
+    BOOST_CHECK(!t.isLevelAndAbove);
+    BOOST_CHECK(!t.isLevelAndBelow);
+
+    SelectorElement u("info+:qmf::");
+    BOOST_CHECK_EQUAL(u.levelStr, "info");
+    BOOST_CHECK_EQUAL(u.patternStr, "qmf::");
+    BOOST_CHECK_EQUAL(u.level, info);
+    BOOST_CHECK(!u.isDisable);
+    BOOST_CHECK(!u.isCategory);
+    BOOST_CHECK(u.isLevelAndAbove);
+    BOOST_CHECK(!u.isLevelAndBelow);
+
+    SelectorElement v("critical-");
+    BOOST_CHECK_EQUAL(v.levelStr, "critical");
+    BOOST_CHECK_EQUAL(v.patternStr, "");
+    BOOST_CHECK_EQUAL(v.level, critical);
+    BOOST_CHECK(!v.isDisable);
+    BOOST_CHECK(!v.isCategory);
+    BOOST_CHECK(!v.isLevelAndAbove);
+    BOOST_CHECK(v.isLevelAndBelow);
+
+    SelectorElement w("!warning-:Management");
+    BOOST_CHECK_EQUAL(w.levelStr, "warning");
+    BOOST_CHECK_EQUAL(w.patternStr, "Management");
+    BOOST_CHECK_EQUAL(w.level, warning);
+    BOOST_CHECK_EQUAL(w.category, management);
+    BOOST_CHECK(w.isDisable);
+    BOOST_CHECK(w.isCategory);
+    BOOST_CHECK(!w.isLevelAndAbove);
+    BOOST_CHECK(w.isLevelAndBelow);
+}
+
 QPID_AUTO_TEST_SUITE_END()
 
 }} // namespace qpid::tests



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org