blob: 9d9928d1700bfb1e10196f642d123bf3ff4b5a17 [file]
/*
* 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 <log4cxx/logger.h>
#include <log4cxx/hierarchy.h>
#include <log4cxx/level.h>
#include "logunit.h"
#include <log4cxx/spi/loggerfactory.h>
#include <log4cxx/helpers/transcoder.h>
/****
This comprehensive test suite verifies that Logger::m_threshold always equals Logger::getEffectiveLevel()->toInt().
Basic Scenarios (Tests 1-6)
• Root logger initialization
• Single logger level setting
• Simple inheritance
• Two-level hierarchies with inheritance and overrides
Multi-Level Hierarchies (Tests 7-10)
• Three and four-level hierarchies
• Various override patterns (middle, leaf, mixed)
Dynamic Parent Changes (Tests 11-13)
• Setting parent from null
• Changing parents
• Multiple parent reassignments
Level Propagation (Tests 14-16)
• Root level changes propagating to children
• Parent changes propagating to grandchildren
• Verification that overridden children don't change
Complex Hierarchies (Tests 17-19)
• Mixed level configurations
• Sibling independence
• Deep hierarchies (7+ levels)
Null Level Handling (Tests 20-22)
• Setting level to null and inheritance
• Toggling between null and values
• Null levels with parent changes
Edge Cases (Tests 23-25)
• All standard levels (OFF, FATAL, ERROR, WARN, INFO, DEBUG, TRACE, ALL)
• Rapid level changes
• Interleaved parent and child changes
Creation Order (Tests 26-28)
• Child created before parent
• Provision node scenarios
• Out-of-order creation
Advanced Scenarios (Tests 29-50)
• Multiple children before parent
• Complex interleaved creation
• Wide hierarchies (many siblings)
• Deep hierarchies with alternating overrides
• Same parent reassignment
• Root affecting entire hierarchy
• Mixed null and non-null levels
• Multiple parent changes with verification
• Grandchildren before ancestors
• Stress tests with many changes
• Different name patterns
• All-null chains except root
Concurrent Branches (Tests 41-50)
• Multiple independent branches
• Cross-branch changes
• Extremely deep hierarchies (50 levels)
• Logger retrieval consistency
• Factory-created loggers
Special Patterns (Tests 51-65)
• Parent-child swaps
• All same level
• Rapid reassignments
• Zigzag patterns
• Level removal and re-addition
• Diamond hierarchies
• Very long names
• Same level multiple times
• Complex mixed operations
• Empty and single-character names
• Final comprehensive stress test
***/
using namespace log4cxx;
LOGUNIT_CLASS(LoggerThresholdConsistencyTest)
{
LOGUNIT_TEST_SUITE(LoggerThresholdConsistencyTest);
// Basic hierarchy tests
LOGUNIT_TEST(testRootLoggerInitialState);
LOGUNIT_TEST(testSingleLoggerSetLevel);
LOGUNIT_TEST(testSingleLoggerInheritsFromRoot);
// Simple parent-child tests
LOGUNIT_TEST(testTwoLevelHierarchyChildInherits);
LOGUNIT_TEST(testTwoLevelHierarchyChildOverrides);
LOGUNIT_TEST(testTwoLevelHierarchyParentChanges);
// Multi-level hierarchy tests
LOGUNIT_TEST(testThreeLevelHierarchyAllInherit);
LOGUNIT_TEST(testThreeLevelHierarchyMiddleOverrides);
LOGUNIT_TEST(testThreeLevelHierarchyLeafOverrides);
LOGUNIT_TEST(testFourLevelHierarchyMixedOverrides);
// Dynamic parent change tests
LOGUNIT_TEST(testSetParentFromNullToValid);
LOGUNIT_TEST(testSetParentChangeParent);
LOGUNIT_TEST(testSetParentMultipleTimes);
// Level change propagation tests
LOGUNIT_TEST(testRootLevelChangePropagatesToChildren);
LOGUNIT_TEST(testParentLevelChangePropagatesToGrandchildren);
LOGUNIT_TEST(testLevelChangeDoesNotPropagateToOverriddenChildren);
// Complex hierarchy tests
LOGUNIT_TEST(testComplexHierarchyWithMixedLevels);
LOGUNIT_TEST(testSiblingLoggersIndependent);
LOGUNIT_TEST(testDeepHierarchyInheritance);
// Level set to null tests
LOGUNIT_TEST(testSetLevelToNullInheritsFromParent);
LOGUNIT_TEST(testSetLevelToNullThenBackToValue);
LOGUNIT_TEST(testChildSetToNullAfterParentChange);
// Edge cases
LOGUNIT_TEST(testAllStandardLevels);
LOGUNIT_TEST(testRapidLevelChanges);
LOGUNIT_TEST(testParentAndChildLevelChangesInterleaved);
// Hierarchy reorganization tests
LOGUNIT_TEST(testLoggerCreationOrderDoesNotMatter);
LOGUNIT_TEST(testChildCreatedBeforeParent);
LOGUNIT_TEST(testProvisionNodeScenario);
// Additional miscellaneous tests
LOGUNIT_TEST(testMultipleChildrenBeforeParent);
LOGUNIT_TEST(testComplexInterleavedCreationAndLevelSetting);
LOGUNIT_TEST(testWideHierarchy);
LOGUNIT_TEST(testDeepHierarchyAlternatingOverrides);
LOGUNIT_TEST(testSetParentToSameParent);
LOGUNIT_TEST(testRootLoggerAffectsEntireHierarchy);
LOGUNIT_TEST(testMixedNullAndNonNullLevels);
LOGUNIT_TEST(testThresholdAfterMultipleParentChanges);
LOGUNIT_TEST(testGrandchildBeforeParentAndMiddle);
LOGUNIT_TEST(testStressTestManyLevelChanges);
LOGUNIT_TEST(testDifferentNamePatterns);
LOGUNIT_TEST(testParentChainAllNullExceptRoot);
LOGUNIT_TEST(testConcurrentHierarchyBranches);
LOGUNIT_TEST(testSetLevelOnLoggerWithExistingChildren);
LOGUNIT_TEST(testAlternatingSetLevelAndSetParent);
LOGUNIT_TEST(testOffAndAllLevels);
LOGUNIT_TEST(testComplexProvisionNodeScenario);
LOGUNIT_TEST(testMultipleSiblingsWithDifferentLevels);
LOGUNIT_TEST(testParentChainWithGaps);
LOGUNIT_TEST(testThresholdAfterHierarchyOperations);
LOGUNIT_TEST(testCrossBranchHierarchyChanges);
LOGUNIT_TEST(testExtremelyDeepHierarchy);
LOGUNIT_TEST(testThresholdConsistencyDuringRetrieval);
LOGUNIT_TEST(testThresholdConsistencyWithLoggerFactory);
LOGUNIT_TEST(testThresholdAfterParentChildSwap);
LOGUNIT_TEST(testThresholdWithAllSameLevel);
LOGUNIT_TEST(testThresholdAfterRapidParentReassignments);
LOGUNIT_TEST(testThresholdWithZigzagLevelPattern);
LOGUNIT_TEST(testThresholdAfterRemovingAndReaddingLevels);
LOGUNIT_TEST(testThresholdWithDiamondHierarchy);
LOGUNIT_TEST(testThresholdWithVeryLongLoggerNames);
LOGUNIT_TEST(testThresholdAfterSettingSameLevelMultipleTimes);
LOGUNIT_TEST(testComplexMixedOperations);
LOGUNIT_TEST(testThresholdAfterParentChangeWithGrandchildren);
LOGUNIT_TEST(testThresholdWithEmptyLoggerName);
LOGUNIT_TEST(testThresholdWithSingleCharacterNames);
LOGUNIT_TEST(testFinalComprehensiveStressTest);
LOGUNIT_TEST_SUITE_END();
private:
HierarchyPtr hierarchy;
public:
void setUp() override
{
hierarchy = Hierarchy::create();
}
void tearDown() override
{
hierarchy->resetConfiguration();
hierarchy.reset();
}
void assertThresholdConsistent(const LoggerPtr& logger)
{
LOG4CXX_ENCODE_CHAR(name, logger->getName());
LOGUNIT_ASSERT_MESSAGE(logger->isThresholdValid()
, "threshold does not match getEffectiveLevel()->toInt() for logger: " + name);
}
void assertThresholdIs(const LevelPtr& level, const LoggerPtr& logger)
{
LOG4CXX_ENCODE_CHAR(levelName, level->toString());
LOG4CXX_ENCODE_CHAR(loggerName, logger->getName());
LOGUNIT_ASSERT_MESSAGE(logger->isThresholdEqualTo(level)
, "threshold is not " + levelName + " for logger: " + loggerName);
}
void assertThresholdIs(const LoggerPtr& other, const LoggerPtr& logger)
{
LOG4CXX_ENCODE_CHAR(name1, other->getName());
LOG4CXX_ENCODE_CHAR(name2, logger->getName());
LOGUNIT_ASSERT_MESSAGE(logger->isThresholdEqualTo(other)
, "threshold is not the same as " + name1 + " for logger: " + name2);
}
public:
// Test 1: Root logger initial state
void testRootLoggerInitialState()
{
LoggerPtr root = hierarchy->getRootLogger();
assertThresholdConsistent(root);
}
// Test 2: Single logger set level
void testSingleLoggerSetLevel()
{
LoggerPtr logger = hierarchy->getLogger(LOG4CXX_STR("com.example"));
assertThresholdConsistent(logger);
logger->setLevel(Level::getInfo());
assertThresholdConsistent(logger);
logger->setLevel(Level::getDebug());
assertThresholdConsistent(logger);
logger->setLevel(Level::getError());
assertThresholdConsistent(logger);
}
// Test 3: Single logger inherits from root
void testSingleLoggerInheritsFromRoot()
{
LoggerPtr root = hierarchy->getRootLogger();
LoggerPtr logger = hierarchy->getLogger(LOG4CXX_STR("com.example"));
root->setLevel(Level::getWarn());
assertThresholdConsistent(logger);
root->setLevel(Level::getTrace());
assertThresholdConsistent(logger);
}
// Test 4: Two-level hierarchy - child inherits
void testTwoLevelHierarchyChildInherits()
{
LoggerPtr parent = hierarchy->getLogger(LOG4CXX_STR("com"));
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("com.example"));
parent->setLevel(Level::getInfo());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
parent->setLevel(Level::getError());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
}
// Test 5: Two-level hierarchy - child overrides
void testTwoLevelHierarchyChildOverrides()
{
LoggerPtr parent = hierarchy->getLogger(LOG4CXX_STR("com"));
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("com.example"));
parent->setLevel(Level::getWarn());
child->setLevel(Level::getDebug());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdIs(Level::getWarn(), parent);
assertThresholdIs(Level::getDebug(), child);
}
// Test 6: Two-level hierarchy - parent changes after child override
void testTwoLevelHierarchyParentChanges()
{
LoggerPtr parent = hierarchy->getLogger(LOG4CXX_STR("com"));
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("com.example"));
parent->setLevel(Level::getWarn());
child->setLevel(Level::getDebug());
// Change parent - child should maintain its override
parent->setLevel(Level::getError());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdIs(Level::getDebug(), child);
}
// Test 7: Three-level hierarchy - all inherit
void testThreeLevelHierarchyAllInherit()
{
LoggerPtr root = hierarchy->getRootLogger();
LoggerPtr level1 = hierarchy->getLogger(LOG4CXX_STR("com"));
LoggerPtr level2 = hierarchy->getLogger(LOG4CXX_STR("com.example"));
LoggerPtr level3 = hierarchy->getLogger(LOG4CXX_STR("com.example.app"));
root->setLevel(Level::getInfo());
assertThresholdConsistent(root);
assertThresholdConsistent(level1);
assertThresholdConsistent(level2);
assertThresholdConsistent(level3);
}
// Test 8: Three-level hierarchy - middle overrides
void testThreeLevelHierarchyMiddleOverrides()
{
LoggerPtr root = hierarchy->getRootLogger();
LoggerPtr level1 = hierarchy->getLogger(LOG4CXX_STR("com"));
LoggerPtr level2 = hierarchy->getLogger(LOG4CXX_STR("com.example"));
LoggerPtr level3 = hierarchy->getLogger(LOG4CXX_STR("com.example.app"));
root->setLevel(Level::getError());
level2->setLevel(Level::getDebug());
assertThresholdConsistent(root);
assertThresholdConsistent(level1);
assertThresholdConsistent(level2);
assertThresholdConsistent(level3);
assertThresholdIs(Level::getError(), level1);
assertThresholdIs(Level::getDebug(), level2);
assertThresholdIs(Level::getDebug(), level3);
}
// Test 9: Three-level hierarchy - leaf overrides
void testThreeLevelHierarchyLeafOverrides()
{
LoggerPtr root = hierarchy->getRootLogger();
LoggerPtr level1 = hierarchy->getLogger(LOG4CXX_STR("com"));
LoggerPtr level2 = hierarchy->getLogger(LOG4CXX_STR("com.example"));
LoggerPtr level3 = hierarchy->getLogger(LOG4CXX_STR("com.example.app"));
root->setLevel(Level::getWarn());
level3->setLevel(Level::getTrace());
assertThresholdConsistent(root);
assertThresholdConsistent(level1);
assertThresholdConsistent(level2);
assertThresholdConsistent(level3);
assertThresholdIs(Level::getWarn(), level1);
assertThresholdIs(Level::getWarn(), level2);
assertThresholdIs(Level::getTrace(), level3);
}
// Test 10: Four-level hierarchy - mixed overrides
void testFourLevelHierarchyMixedOverrides()
{
LoggerPtr root = hierarchy->getRootLogger();
LoggerPtr level1 = hierarchy->getLogger(LOG4CXX_STR("org"));
LoggerPtr level2 = hierarchy->getLogger(LOG4CXX_STR("org.apache"));
LoggerPtr level3 = hierarchy->getLogger(LOG4CXX_STR("org.apache.log4cxx"));
LoggerPtr level4 = hierarchy->getLogger(LOG4CXX_STR("org.apache.log4cxx.test"));
root->setLevel(Level::getError());
level2->setLevel(Level::getInfo());
level4->setLevel(Level::getDebug());
assertThresholdConsistent(root);
assertThresholdConsistent(level1);
assertThresholdConsistent(level2);
assertThresholdConsistent(level3);
assertThresholdConsistent(level4);
assertThresholdIs(Level::getError(), level1);
assertThresholdIs(Level::getInfo(), level2);
assertThresholdIs(Level::getInfo(), level3);
assertThresholdIs(Level::getDebug(), level4);
}
// Test 11: Set parent from null to valid
void testSetParentFromNullToValid()
{
LoggerPtr parent = hierarchy->getLogger(LOG4CXX_STR("parent"));
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("child"));
parent->setLevel(Level::getWarn());
child->changeParentTo(parent);
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
}
// Test 12: Change parent
void testSetParentChangeParent()
{
LoggerPtr parent1 = hierarchy->getLogger(LOG4CXX_STR("parent1"));
LoggerPtr parent2 = hierarchy->getLogger(LOG4CXX_STR("parent2"));
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("child"));
parent1->setLevel(Level::getDebug());
parent2->setLevel(Level::getError());
child->changeParentTo(parent1);
assertThresholdConsistent(child);
assertThresholdIs(Level::getDebug(), child);
child->changeParentTo(parent2);
assertThresholdConsistent(child);
assertThresholdIs(Level::getError(), child);
}
// Test 13: Set parent multiple times
void testSetParentMultipleTimes()
{
LoggerPtr root = hierarchy->getRootLogger();
LoggerPtr parent1 = hierarchy->getLogger(LOG4CXX_STR("p1"));
LoggerPtr parent2 = hierarchy->getLogger(LOG4CXX_STR("p2"));
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("child"));
root->setLevel(Level::getFatal());
parent1->setLevel(Level::getInfo());
parent2->setLevel(Level::getDebug());
child->changeParentTo(root);
assertThresholdConsistent(child);
child->changeParentTo(parent1);
assertThresholdConsistent(child);
child->changeParentTo(parent2);
assertThresholdConsistent(child);
child->changeParentTo(root);
assertThresholdConsistent(child);
}
// Test 14: Root level change propagates to children
void testRootLevelChangePropagatesToChildren()
{
LoggerPtr root = hierarchy->getRootLogger();
LoggerPtr child1 = hierarchy->getLogger(LOG4CXX_STR("child1"));
LoggerPtr child2 = hierarchy->getLogger(LOG4CXX_STR("child2"));
LoggerPtr grandchild = hierarchy->getLogger(LOG4CXX_STR("child1.grandchild"));
root->setLevel(Level::getWarn());
assertThresholdConsistent(child1);
assertThresholdConsistent(child2);
assertThresholdConsistent(grandchild);
root->setLevel(Level::getDebug());
assertThresholdConsistent(child1);
assertThresholdConsistent(child2);
assertThresholdConsistent(grandchild);
}
// Test 15: Parent level change propagates to grandchildren
void testParentLevelChangePropagatesToGrandchildren()
{
LoggerPtr root = hierarchy->getRootLogger();
LoggerPtr parent = hierarchy->getLogger(LOG4CXX_STR("parent"));
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("parent.child"));
LoggerPtr grandchild = hierarchy->getLogger(LOG4CXX_STR("parent.child.grandchild"));
root->setLevel(Level::getError());
parent->setLevel(Level::getInfo());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
parent->setLevel(Level::getDebug());
assertThresholdIs(Level::getDebug(), grandchild);
}
// Test 16: Level change does not propagate to overridden children
void testLevelChangeDoesNotPropagateToOverriddenChildren()
{
LoggerPtr root = hierarchy->getRootLogger();
LoggerPtr parent = hierarchy->getLogger(LOG4CXX_STR("parent"));
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("parent.child"));
LoggerPtr grandchild = hierarchy->getLogger(LOG4CXX_STR("parent.child.grandchild"));
root->setLevel(Level::getError());
parent->setLevel(Level::getInfo());
child->setLevel(Level::getDebug());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
// Change parent level
parent->setLevel(Level::getWarn());
// Child should keep its own level
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
assertThresholdIs(Level::getWarn(), parent);
assertThresholdIs(Level::getDebug(), child);
assertThresholdIs(Level::getDebug(), grandchild);
}
// Test 17: Complex hierarchy with mixed levels
void testComplexHierarchyWithMixedLevels()
{
LoggerPtr root = hierarchy->getRootLogger();
LoggerPtr a = hierarchy->getLogger(LOG4CXX_STR("a"));
LoggerPtr ab = hierarchy->getLogger(LOG4CXX_STR("a.b"));
LoggerPtr abc = hierarchy->getLogger(LOG4CXX_STR("a.b.c"));
LoggerPtr abcd = hierarchy->getLogger(LOG4CXX_STR("a.b.c.d"));
LoggerPtr ax = hierarchy->getLogger(LOG4CXX_STR("a.x"));
LoggerPtr axy = hierarchy->getLogger(LOG4CXX_STR("a.x.y"));
root->setLevel(Level::getFatal());
a->setLevel(Level::getError());
abc->setLevel(Level::getDebug());
ax->setLevel(Level::getInfo());
assertThresholdConsistent(root);
assertThresholdConsistent(a);
assertThresholdConsistent(ab);
assertThresholdConsistent(abc);
assertThresholdConsistent(abcd);
assertThresholdConsistent(ax);
assertThresholdConsistent(axy);
assertThresholdIs(Level::getFatal(), root);
assertThresholdIs(Level::getError(), a);
assertThresholdIs(Level::getError(), ab);
assertThresholdIs(Level::getDebug(), abc);
assertThresholdIs(Level::getDebug(), abcd);
assertThresholdIs(Level::getInfo(), ax);
assertThresholdIs(Level::getInfo(), axy);
}
// Test 18: Sibling loggers are independent
void testSiblingLoggersIndependent()
{
LoggerPtr root = hierarchy->getRootLogger();
LoggerPtr sibling1 = hierarchy->getLogger(LOG4CXX_STR("com.example.app1"));
LoggerPtr sibling2 = hierarchy->getLogger(LOG4CXX_STR("com.example.app2"));
LoggerPtr sibling3 = hierarchy->getLogger(LOG4CXX_STR("com.example.app3"));
root->setLevel(Level::getWarn());
sibling1->setLevel(Level::getDebug());
sibling2->setLevel(Level::getError());
// sibling3 inherits
assertThresholdConsistent(sibling1);
assertThresholdConsistent(sibling2);
assertThresholdConsistent(sibling3);
assertThresholdIs(Level::getDebug(), sibling1);
assertThresholdIs(Level::getError(), sibling2);
assertThresholdIs(Level::getWarn(), sibling3);
// Change sibling1 - should not affect others
sibling1->setLevel(Level::getTrace());
assertThresholdConsistent(sibling1);
assertThresholdConsistent(sibling2);
assertThresholdConsistent(sibling3);
assertThresholdIs(Level::getTrace(), sibling1);
assertThresholdIs(Level::getError(), sibling2);
assertThresholdIs(Level::getWarn(), sibling3);
}
// Test 19: Deep hierarchy inheritance
void testDeepHierarchyInheritance()
{
LoggerPtr root = hierarchy->getRootLogger();
LoggerPtr l1 = hierarchy->getLogger(LOG4CXX_STR("a"));
LoggerPtr l2 = hierarchy->getLogger(LOG4CXX_STR("a.b"));
LoggerPtr l3 = hierarchy->getLogger(LOG4CXX_STR("a.b.c"));
LoggerPtr l4 = hierarchy->getLogger(LOG4CXX_STR("a.b.c.d"));
LoggerPtr l5 = hierarchy->getLogger(LOG4CXX_STR("a.b.c.d.e"));
LoggerPtr l6 = hierarchy->getLogger(LOG4CXX_STR("a.b.c.d.e.f"));
LoggerPtr l7 = hierarchy->getLogger(LOG4CXX_STR("a.b.c.d.e.f.g"));
root->setLevel(Level::getInfo());
assertThresholdConsistent(root);
assertThresholdConsistent(l1);
assertThresholdConsistent(l2);
assertThresholdConsistent(l3);
assertThresholdConsistent(l4);
assertThresholdConsistent(l5);
assertThresholdConsistent(l6);
assertThresholdConsistent(l7);
// All should inherit INFO
assertThresholdIs(Level::getInfo(), l1);
assertThresholdIs(Level::getInfo(), l7);
// Set middle level
l4->setLevel(Level::getDebug());
assertThresholdConsistent(l1);
assertThresholdConsistent(l2);
assertThresholdConsistent(l3);
assertThresholdConsistent(l4);
assertThresholdConsistent(l5);
assertThresholdConsistent(l6);
assertThresholdConsistent(l7);
assertThresholdIs(Level::getInfo(), l3);
assertThresholdIs(Level::getDebug(), l4);
assertThresholdIs(Level::getDebug(), l5);
assertThresholdIs(Level::getDebug(), l7);
}
// Test 20: Set level to null - inherits from parent
void testSetLevelToNullInheritsFromParent()
{
LoggerPtr parent = hierarchy->getLogger(LOG4CXX_STR("parent"));
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("parent.child"));
parent->setLevel(Level::getWarn());
child->setLevel(Level::getDebug());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdIs(Level::getDebug(), child);
// Set child level to null - should inherit from parent
child->setLevel(LevelPtr());
assertThresholdConsistent(child);
assertThresholdIs(Level::getWarn(), child);
}
// Test 21: Set level to null then back to value
void testSetLevelToNullThenBackToValue()
{
LoggerPtr parent = hierarchy->getLogger(LOG4CXX_STR("parent"));
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("parent.child"));
parent->setLevel(Level::getError());
child->setLevel(Level::getInfo());
assertThresholdConsistent(child);
assertThresholdIs(Level::getInfo(), child);
child->setLevel(LevelPtr());
assertThresholdConsistent(child);
assertThresholdIs(Level::getError(), child);
child->setLevel(Level::getDebug());
assertThresholdConsistent(child);
assertThresholdIs(Level::getDebug(), child);
child->setLevel(LevelPtr());
assertThresholdConsistent(child);
assertThresholdIs(Level::getError(), child);
}
// Test 22: Child set to null after parent change
void testChildSetToNullAfterParentChange()
{
LoggerPtr parent = hierarchy->getLogger(LOG4CXX_STR("parent"));
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("parent.child"));
parent->setLevel(Level::getInfo());
child->setLevel(Level::getDebug());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
// Set child to null
child->setLevel(LevelPtr());
assertThresholdConsistent(child);
assertThresholdIs(Level::getInfo(), child);
// Change parent level - child should follow
parent->setLevel(Level::getWarn());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdIs(Level::getWarn(), child);
parent->setLevel(Level::getTrace());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdIs(Level::getTrace(), child);
}
// Test 23: All standard levels
void testAllStandardLevels()
{
LoggerPtr logger = hierarchy->getLogger(LOG4CXX_STR("test"));
LevelPtr levels[] = {
Level::getOff(),
Level::getFatal(),
Level::getError(),
Level::getWarn(),
Level::getInfo(),
Level::getDebug(),
Level::getTrace(),
Level::getAll()
};
for (size_t i = 0; i < sizeof(levels)/sizeof(levels[0]); ++i)
{
logger->setLevel(levels[i]);
assertThresholdConsistent(logger);
assertThresholdIs(levels[i], logger);
}
}
// Test 24: Rapid level changes
void testRapidLevelChanges()
{
LoggerPtr logger = hierarchy->getLogger(LOG4CXX_STR("rapid"));
for (int i = 0; i < 100; ++i)
{
logger->setLevel(Level::getDebug());
assertThresholdConsistent(logger);
logger->setLevel(Level::getInfo());
assertThresholdConsistent(logger);
logger->setLevel(Level::getWarn());
assertThresholdConsistent(logger);
logger->setLevel(Level::getError());
assertThresholdConsistent(logger);
logger->setLevel(LevelPtr());
assertThresholdConsistent(logger);
}
}
// Test 25: Parent and child level changes interleaved
void testParentAndChildLevelChangesInterleaved()
{
LoggerPtr parent = hierarchy->getLogger(LOG4CXX_STR("parent"));
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("parent.child"));
LoggerPtr grandchild = hierarchy->getLogger(LOG4CXX_STR("parent.child.grandchild"));
parent->setLevel(Level::getInfo());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
child->setLevel(Level::getDebug());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
parent->setLevel(Level::getWarn());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
grandchild->setLevel(Level::getTrace());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
child->setLevel(LevelPtr());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
assertThresholdIs(Level::getWarn(), parent);
assertThresholdIs(Level::getWarn(), child);
assertThresholdIs(Level::getTrace(), grandchild);
parent->setLevel(Level::getError());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
assertThresholdIs(Level::getError(), child);
assertThresholdIs(Level::getTrace(), grandchild);
}
// Test 26: Logger creation order does not matter
void testLoggerCreationOrderDoesNotMatter()
{
// Create in hierarchical order
LoggerPtr a1 = hierarchy->getLogger(LOG4CXX_STR("order1"));
LoggerPtr b1 = hierarchy->getLogger(LOG4CXX_STR("order1.child"));
LoggerPtr c1 = hierarchy->getLogger(LOG4CXX_STR("order1.child.grandchild"));
a1->setLevel(Level::getWarn());
assertThresholdConsistent(a1);
assertThresholdConsistent(b1);
assertThresholdConsistent(c1);
// Create in reverse order
LoggerPtr c2 = hierarchy->getLogger(LOG4CXX_STR("order2.child.grandchild"));
LoggerPtr b2 = hierarchy->getLogger(LOG4CXX_STR("order2.child"));
LoggerPtr a2 = hierarchy->getLogger(LOG4CXX_STR("order2"));
a2->setLevel(Level::getWarn());
assertThresholdConsistent(a2);
assertThresholdConsistent(b2);
assertThresholdConsistent(c2);
// Both should have same threshold
assertThresholdIs(c1, c2);
}
// Test 27: Child created before parent
void testChildCreatedBeforeParent()
{
// Create child first
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("parent.child"));
LoggerPtr grandchild = hierarchy->getLogger(LOG4CXX_STR("parent.child.grandchild"));
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
// Now create parent and set its level
LoggerPtr parent = hierarchy->getLogger(LOG4CXX_STR("parent"));
parent->setLevel(Level::getInfo());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
// Child and grandchild should now inherit from parent
assertThresholdIs(Level::getInfo(), child);
assertThresholdIs(Level::getInfo(), grandchild);
// Change parent level
parent->setLevel(Level::getDebug());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
assertThresholdIs(Level::getDebug(), child);
assertThresholdIs(Level::getDebug(), grandchild);
}
// Test 28: Provision node scenario
void testProvisionNodeScenario()
{
// Create grandchild before intermediate parent exists
LoggerPtr grandchild1 = hierarchy->getLogger(LOG4CXX_STR("a.b.c.d"));
LoggerPtr grandchild2 = hierarchy->getLogger(LOG4CXX_STR("a.b.c.e"));
LoggerPtr grandchild3 = hierarchy->getLogger(LOG4CXX_STR("a.b.c.f"));
assertThresholdConsistent(grandchild1);
assertThresholdConsistent(grandchild2);
assertThresholdConsistent(grandchild3);
// Create root ancestor
LoggerPtr a = hierarchy->getLogger(LOG4CXX_STR("a"));
a->setLevel(Level::getWarn());
assertThresholdConsistent(a);
assertThresholdConsistent(grandchild1);
assertThresholdConsistent(grandchild2);
assertThresholdConsistent(grandchild3);
assertThresholdIs(Level::getWarn(), grandchild1);
assertThresholdIs(Level::getWarn(), grandchild2);
assertThresholdIs(Level::getWarn(), grandchild3);
// Now create intermediate parent
LoggerPtr abc = hierarchy->getLogger(LOG4CXX_STR("a.b.c"));
abc->setLevel(Level::getDebug());
assertThresholdConsistent(a);
assertThresholdConsistent(abc);
assertThresholdConsistent(grandchild1);
assertThresholdConsistent(grandchild2);
assertThresholdConsistent(grandchild3);
assertThresholdIs(Level::getWarn(), a);
assertThresholdIs(Level::getDebug(), abc);
assertThresholdIs(Level::getDebug(), grandchild1);
assertThresholdIs(Level::getDebug(), grandchild2);
assertThresholdIs(Level::getDebug(), grandchild3);
// Override one grandchild
grandchild2->setLevel(Level::getTrace());
assertThresholdConsistent(grandchild2);
assertThresholdIs(Level::getTrace(), grandchild2);
// Change intermediate parent - should not affect overridden grandchild
abc->setLevel(Level::getError());
assertThresholdConsistent(abc);
assertThresholdConsistent(grandchild1);
assertThresholdConsistent(grandchild2);
assertThresholdConsistent(grandchild3);
assertThresholdIs(Level::getError(), grandchild1);
assertThresholdIs(Level::getTrace(), grandchild2);
assertThresholdIs(Level::getError(), grandchild3);
}
// Additional Test 29: Multiple children created before parent
void testMultipleChildrenBeforeParent()
{
LoggerPtr child1 = hierarchy->getLogger(LOG4CXX_STR("base.child1"));
LoggerPtr child2 = hierarchy->getLogger(LOG4CXX_STR("base.child2"));
LoggerPtr child3 = hierarchy->getLogger(LOG4CXX_STR("base.child3"));
LoggerPtr grandchild1 = hierarchy->getLogger(LOG4CXX_STR("base.child1.grandchild"));
assertThresholdConsistent(child1);
assertThresholdConsistent(child2);
assertThresholdConsistent(child3);
assertThresholdConsistent(grandchild1);
// Now create parent
LoggerPtr base = hierarchy->getLogger(LOG4CXX_STR("base"));
base->setLevel(Level::getInfo());
assertThresholdConsistent(base);
assertThresholdConsistent(child1);
assertThresholdConsistent(child2);
assertThresholdConsistent(child3);
assertThresholdConsistent(grandchild1);
assertThresholdIs(Level::getInfo(), child1);
assertThresholdIs(Level::getInfo(), child2);
assertThresholdIs(Level::getInfo(), child3);
assertThresholdIs(Level::getInfo(), grandchild1);
}
// Additional Test 30: Complex interleaved creation and level setting
void testComplexInterleavedCreationAndLevelSetting()
{
LoggerPtr root = hierarchy->getRootLogger();
root->setLevel(Level::getFatal());
LoggerPtr c = hierarchy->getLogger(LOG4CXX_STR("a.b.c"));
assertThresholdConsistent(c);
assertThresholdIs(Level::getFatal(), c);
LoggerPtr a = hierarchy->getLogger(LOG4CXX_STR("a"));
a->setLevel(Level::getError());
assertThresholdConsistent(a);
assertThresholdConsistent(c);
assertThresholdIs(Level::getError(), c);
LoggerPtr d = hierarchy->getLogger(LOG4CXX_STR("a.b.c.d"));
assertThresholdConsistent(d);
assertThresholdIs(Level::getError(), d);
c->setLevel(Level::getDebug());
assertThresholdConsistent(a);
assertThresholdConsistent(c);
assertThresholdConsistent(d);
assertThresholdIs(Level::getError(), a);
assertThresholdIs(Level::getDebug(), c);
assertThresholdIs(Level::getDebug(), d);
LoggerPtr b = hierarchy->getLogger(LOG4CXX_STR("a.b"));
b->setLevel(Level::getWarn());
assertThresholdConsistent(a);
assertThresholdConsistent(b);
assertThresholdConsistent(c);
assertThresholdConsistent(d);
assertThresholdIs(Level::getError(), a);
assertThresholdIs(Level::getWarn(), b);
assertThresholdIs(Level::getDebug(), c);
assertThresholdIs(Level::getDebug(), d);
// Set c to null - should inherit from b
c->setLevel(LevelPtr());
assertThresholdConsistent(c);
assertThresholdConsistent(d);
assertThresholdIs(Level::getWarn(), c);
assertThresholdIs(Level::getWarn(), d);
}
// Additional Test 31: Wide hierarchy (many siblings)
void testWideHierarchy()
{
LoggerPtr parent = hierarchy->getLogger(LOG4CXX_STR("parent"));
parent->setLevel(Level::getInfo());
std::vector<LoggerPtr> children;
for (int i = 0; i < 20; ++i)
{
std::ostringstream oss;
oss << "parent.child" << i;
LOG4CXX_DECODE_CHAR(category, oss.str());
LoggerPtr child = hierarchy->getLogger(category);
children.push_back(child);
assertThresholdConsistent(child);
assertThresholdIs(Level::getInfo(), child);
}
// Override some children
children[5]->setLevel(Level::getDebug());
children[10]->setLevel(Level::getWarn());
children[15]->setLevel(Level::getError());
for (size_t i = 0; i < children.size(); ++i)
{
assertThresholdConsistent(children[i]);
}
assertThresholdIs(Level::getDebug(), children[5]);
assertThresholdIs(Level::getWarn(), children[10]);
assertThresholdIs(Level::getError(), children[15]);
assertThresholdIs(Level::getInfo(), children[0]);
assertThresholdIs(Level::getInfo(), children[19]);
// Change parent level
parent->setLevel(Level::getTrace());
for (size_t i = 0; i < children.size(); ++i)
{
assertThresholdConsistent(children[i]);
}
// Overridden children should keep their levels
assertThresholdIs(Level::getDebug(), children[5]);
assertThresholdIs(Level::getWarn(), children[10]);
assertThresholdIs(Level::getError(), children[15]);
// Non-overridden should inherit new level
assertThresholdIs(Level::getTrace(), children[0]);
assertThresholdIs(Level::getTrace(), children[19]);
}
// Additional Test 32: Deep hierarchy with alternating overrides
void testDeepHierarchyAlternatingOverrides()
{
LoggerPtr root = hierarchy->getRootLogger();
root->setLevel(Level::getError());
std::vector<LoggerPtr> loggers;
loggers.push_back(root);
LogString name = LOG4CXX_STR("a");
for (int i = 0; i < 10; ++i)
{
LoggerPtr logger = hierarchy->getLogger(name);
loggers.push_back(logger);
// Set level on even indices
if (i % 2 == 0)
{
logger->setLevel(Level::getDebug());
}
assertThresholdConsistent(logger);
name += LOG4CXX_STR(".b");
}
// Verify all thresholds are consistent
for (size_t i = 0; i < loggers.size(); ++i)
{
assertThresholdConsistent(loggers[i]);
}
// Verify expected levels
assertThresholdIs(Level::getError(), loggers[0]); // root
assertThresholdIs(Level::getDebug(), loggers[1]); // a (i=0, even)
assertThresholdIs(Level::getDebug(), loggers[2]); // a.b (i=1, odd, inherits)
assertThresholdIs(Level::getDebug(), loggers[3]); // a.b.b (i=2, even)
assertThresholdIs(Level::getDebug(), loggers[4]); // a.b.b.b (i=3, odd, inherits)
}
// Additional Test 33: Set parent to same parent (no-op)
void testSetParentToSameParent()
{
LoggerPtr parent = hierarchy->getLogger(LOG4CXX_STR("parent"));
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("parent.child"));
parent->setLevel(Level::getInfo());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
LoggerPtr currentParent = child->getParent();
LOGUNIT_ASSERT(currentParent != nullptr);
// Set parent to same parent (should be no-op)
child->changeParentTo(currentParent);
assertThresholdConsistent(child);
assertThresholdIs(Level::getInfo(), child);
}
// Additional Test 34: Root logger level changes affect entire hierarchy
void testRootLoggerAffectsEntireHierarchy()
{
LoggerPtr root = hierarchy->getRootLogger();
LoggerPtr a = hierarchy->getLogger(LOG4CXX_STR("a"));
LoggerPtr ab = hierarchy->getLogger(LOG4CXX_STR("a.b"));
LoggerPtr abc = hierarchy->getLogger(LOG4CXX_STR("a.b.c"));
LoggerPtr x = hierarchy->getLogger(LOG4CXX_STR("x"));
LoggerPtr xy = hierarchy->getLogger(LOG4CXX_STR("x.y"));
root->setLevel(Level::getWarn());
assertThresholdConsistent(root);
assertThresholdConsistent(a);
assertThresholdConsistent(ab);
assertThresholdConsistent(abc);
assertThresholdConsistent(x);
assertThresholdConsistent(xy);
assertThresholdIs(Level::getWarn(), a);
assertThresholdIs(Level::getWarn(), ab);
assertThresholdIs(Level::getWarn(), abc);
assertThresholdIs(Level::getWarn(), x);
assertThresholdIs(Level::getWarn(), xy);
root->setLevel(Level::getDebug());
assertThresholdConsistent(root);
assertThresholdConsistent(a);
assertThresholdConsistent(ab);
assertThresholdConsistent(abc);
assertThresholdConsistent(x);
assertThresholdConsistent(xy);
assertThresholdIs(Level::getDebug(), a);
assertThresholdIs(Level::getDebug(), ab);
assertThresholdIs(Level::getDebug(), abc);
assertThresholdIs(Level::getDebug(), x);
assertThresholdIs(Level::getDebug(), xy);
}
// Additional Test 35: Mixed null and non-null levels in hierarchy
void testMixedNullAndNonNullLevels()
{
LoggerPtr root = hierarchy->getRootLogger();
LoggerPtr a = hierarchy->getLogger(LOG4CXX_STR("a"));
LoggerPtr ab = hierarchy->getLogger(LOG4CXX_STR("a.b"));
LoggerPtr abc = hierarchy->getLogger(LOG4CXX_STR("a.b.c"));
LoggerPtr abcd = hierarchy->getLogger(LOG4CXX_STR("a.b.c.d"));
root->setLevel(Level::getError());
a->setLevel(LevelPtr()); // null - should inherit from root
ab->setLevel(Level::getInfo());
abc->setLevel(LevelPtr()); // null - should inherit from ab
abcd->setLevel(Level::getDebug());
assertThresholdConsistent(root);
assertThresholdConsistent(a);
assertThresholdConsistent(ab);
assertThresholdConsistent(abc);
assertThresholdConsistent(abcd);
assertThresholdIs(Level::getError(), root);
assertThresholdIs(Level::getError(), a);
assertThresholdIs(Level::getInfo(), ab);
assertThresholdIs(Level::getInfo(), abc);
assertThresholdIs(Level::getDebug(), abcd);
// Change ab level - abc should follow
ab->setLevel(Level::getWarn());
assertThresholdConsistent(ab);
assertThresholdConsistent(abc);
assertThresholdConsistent(abcd);
assertThresholdIs(Level::getWarn(), abc);
assertThresholdIs(Level::getDebug(), abcd);
}
// Additional Test 36: Verify threshold after multiple parent changes
void testThresholdAfterMultipleParentChanges()
{
LoggerPtr p1 = hierarchy->getLogger(LOG4CXX_STR("parent1"));
LoggerPtr p2 = hierarchy->getLogger(LOG4CXX_STR("parent2"));
LoggerPtr p3 = hierarchy->getLogger(LOG4CXX_STR("parent3"));
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("orphan"));
p1->setLevel(Level::getTrace());
p2->setLevel(Level::getInfo());
p3->setLevel(Level::getFatal());
child->changeParentTo(p1);
assertThresholdConsistent(child);
assertThresholdIs(Level::getTrace(), child);
child->changeParentTo(p2);
assertThresholdConsistent(child);
assertThresholdIs(Level::getInfo(), child);
child->changeParentTo(p3);
assertThresholdConsistent(child);
assertThresholdIs(Level::getFatal(), child);
child->changeParentTo(p1);
assertThresholdConsistent(child);
assertThresholdIs(Level::getTrace(), child);
// Set child's own level
child->setLevel(Level::getWarn());
assertThresholdConsistent(child);
assertThresholdIs(Level::getWarn(), child);
// Change parent - child should keep its level
child->changeParentTo(p2);
assertThresholdConsistent(child);
assertThresholdIs(Level::getWarn(), child);
}
// Additional Test 37: Grandchild created before parent and middle ancestor
void testGrandchildBeforeParentAndMiddle()
{
LoggerPtr grandchild = hierarchy->getLogger(LOG4CXX_STR("a.b.c.d.e.f"));
assertThresholdConsistent(grandchild);
LoggerPtr root = hierarchy->getRootLogger();
root->setLevel(Level::getError());
assertThresholdConsistent(grandchild);
assertThresholdIs(Level::getError(), grandchild);
LoggerPtr middle = hierarchy->getLogger(LOG4CXX_STR("a.b.c"));
middle->setLevel(Level::getInfo());
assertThresholdConsistent(middle);
assertThresholdConsistent(grandchild);
assertThresholdIs(Level::getInfo(), grandchild);
LoggerPtr top = hierarchy->getLogger(LOG4CXX_STR("a"));
top->setLevel(Level::getWarn());
assertThresholdConsistent(top);
assertThresholdConsistent(middle);
assertThresholdConsistent(grandchild);
// grandchild should still inherit from middle (closest ancestor with level)
assertThresholdIs(Level::getWarn(), top);
assertThresholdIs(Level::getInfo(), middle);
assertThresholdIs(Level::getInfo(), grandchild);
}
// Additional Test 38: Stress test - many level changes
void testStressTestManyLevelChanges()
{
LoggerPtr root = hierarchy->getRootLogger();
LoggerPtr parent = hierarchy->getLogger(LOG4CXX_STR("stress.parent"));
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("stress.parent.child"));
LoggerPtr grandchild = hierarchy->getLogger(LOG4CXX_STR("stress.parent.child.grandchild"));
LevelPtr levels[] = {
Level::getTrace(),
Level::getDebug(),
Level::getInfo(),
Level::getWarn(),
Level::getError(),
Level::getFatal()
};
for (int iteration = 0; iteration < 50; ++iteration)
{
for (size_t i = 0; i < sizeof(levels)/sizeof(levels[0]); ++i)
{
root->setLevel(levels[i]);
assertThresholdConsistent(root);
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
parent->setLevel(levels[(i + 1) % (sizeof(levels)/sizeof(levels[0]))]);
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
child->setLevel(levels[(i + 2) % (sizeof(levels)/sizeof(levels[0]))]);
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
// Set to null and verify inheritance
child->setLevel(LevelPtr());
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
}
}
}
// Additional Test 39: Verify consistency across different name patterns
void testDifferentNamePatterns()
{
// Single segment names
LoggerPtr single1 = hierarchy->getLogger(LOG4CXX_STR("logger1"));
LoggerPtr single2 = hierarchy->getLogger(LOG4CXX_STR("logger2"));
// Multi-segment names
LoggerPtr multi1 = hierarchy->getLogger(LOG4CXX_STR("com.example.app"));
LoggerPtr multi2 = hierarchy->getLogger(LOG4CXX_STR("org.apache.log4cxx"));
// Very long names
LoggerPtr longName = hierarchy->getLogger(LOG4CXX_STR("a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p"));
// Names with numbers
LoggerPtr numbered = hierarchy->getLogger(LOG4CXX_STR("logger.v1.module2.class3"));
LoggerPtr root = hierarchy->getRootLogger();
root->setLevel(Level::getInfo());
assertThresholdConsistent(single1);
assertThresholdConsistent(single2);
assertThresholdConsistent(multi1);
assertThresholdConsistent(multi2);
assertThresholdConsistent(longName);
assertThresholdConsistent(numbered);
single1->setLevel(Level::getDebug());
assertThresholdConsistent(single1);
LoggerPtr comExample = hierarchy->getLogger(LOG4CXX_STR("com.example"));
comExample->setLevel(Level::getWarn());
assertThresholdConsistent(comExample);
assertThresholdConsistent(multi1);
assertThresholdIs(Level::getWarn(), multi1);
}
// Additional Test 40: Parent chain with all null levels except root
void testParentChainAllNullExceptRoot()
{
LoggerPtr root = hierarchy->getRootLogger();
LoggerPtr a = hierarchy->getLogger(LOG4CXX_STR("a"));
LoggerPtr ab = hierarchy->getLogger(LOG4CXX_STR("a.b"));
LoggerPtr abc = hierarchy->getLogger(LOG4CXX_STR("a.b.c"));
LoggerPtr abcd = hierarchy->getLogger(LOG4CXX_STR("a.b.c.d"));
root->setLevel(Level::getWarn());
// All others have null level (default)
assertThresholdConsistent(root);
assertThresholdConsistent(a);
assertThresholdConsistent(ab);
assertThresholdConsistent(abc);
assertThresholdConsistent(abcd);
// All should inherit from root
assertThresholdIs(Level::getWarn(), a);
assertThresholdIs(Level::getWarn(), ab);
assertThresholdIs(Level::getWarn(), abc);
assertThresholdIs(Level::getWarn(), abcd);
// Change root
root->setLevel(Level::getDebug());
assertThresholdConsistent(root);
assertThresholdConsistent(a);
assertThresholdConsistent(ab);
assertThresholdConsistent(abc);
assertThresholdConsistent(abcd);
assertThresholdIs(Level::getDebug(), a);
assertThresholdIs(Level::getDebug(), ab);
assertThresholdIs(Level::getDebug(), abc);
assertThresholdIs(Level::getDebug(), abcd);
}
// Additional Test 41: Concurrent hierarchy branches
void testConcurrentHierarchyBranches()
{
LoggerPtr root = hierarchy->getRootLogger();
root->setLevel(Level::getError());
// Branch 1: com.example.app
LoggerPtr com = hierarchy->getLogger(LOG4CXX_STR("com"));
LoggerPtr comExample = hierarchy->getLogger(LOG4CXX_STR("com.example"));
LoggerPtr comExampleApp = hierarchy->getLogger(LOG4CXX_STR("com.example.app"));
// Branch 2: org.apache.log4cxx
LoggerPtr org = hierarchy->getLogger(LOG4CXX_STR("org"));
LoggerPtr orgApache = hierarchy->getLogger(LOG4CXX_STR("org.apache"));
LoggerPtr orgApacheLog4cxx = hierarchy->getLogger(LOG4CXX_STR("org.apache.log4cxx"));
// Set different levels on branches
com->setLevel(Level::getInfo());
org->setLevel(Level::getDebug());
assertThresholdConsistent(com);
assertThresholdConsistent(comExample);
assertThresholdConsistent(comExampleApp);
assertThresholdConsistent(org);
assertThresholdConsistent(orgApache);
assertThresholdConsistent(orgApacheLog4cxx);
assertThresholdIs(Level::getInfo(), comExample);
assertThresholdIs(Level::getInfo(), comExampleApp);
assertThresholdIs(Level::getDebug(), orgApache);
assertThresholdIs(Level::getDebug(), orgApacheLog4cxx);
// Override in middle of one branch
comExample->setLevel(Level::getWarn());
assertThresholdConsistent(comExample);
assertThresholdConsistent(comExampleApp);
assertThresholdIs(Level::getWarn(), comExample);
assertThresholdIs(Level::getWarn(), comExampleApp);
// Other branch should be unaffected
assertThresholdConsistent(org);
assertThresholdConsistent(orgApache);
assertThresholdConsistent(orgApacheLog4cxx);
assertThresholdIs(Level::getDebug(), orgApache);
}
// Additional Test 42: Setting level on logger with existing children
void testSetLevelOnLoggerWithExistingChildren()
{
LoggerPtr parent = hierarchy->getLogger(LOG4CXX_STR("parent"));
LoggerPtr child1 = hierarchy->getLogger(LOG4CXX_STR("parent.child1"));
LoggerPtr child2 = hierarchy->getLogger(LOG4CXX_STR("parent.child2"));
LoggerPtr grandchild1 = hierarchy->getLogger(LOG4CXX_STR("parent.child1.grandchild"));
LoggerPtr grandchild2 = hierarchy->getLogger(LOG4CXX_STR("parent.child2.grandchild"));
// All start with root's level
LoggerPtr root = hierarchy->getRootLogger();
root->setLevel(Level::getError());
assertThresholdConsistent(parent);
assertThresholdConsistent(child1);
assertThresholdConsistent(child2);
assertThresholdConsistent(grandchild1);
assertThresholdConsistent(grandchild2);
// Set parent level - should propagate to all children
parent->setLevel(Level::getInfo());
assertThresholdConsistent(parent);
assertThresholdConsistent(child1);
assertThresholdConsistent(child2);
assertThresholdConsistent(grandchild1);
assertThresholdConsistent(grandchild2);
assertThresholdIs(Level::getInfo(), child1);
assertThresholdIs(Level::getInfo(), child2);
assertThresholdIs(Level::getInfo(), grandchild1);
assertThresholdIs(Level::getInfo(), grandchild2);
// Override one child
child1->setLevel(Level::getDebug());
assertThresholdConsistent(child1);
assertThresholdConsistent(grandchild1);
assertThresholdIs(Level::getDebug(), child1);
assertThresholdIs(Level::getDebug(), grandchild1);
// Change parent again - overridden child should keep its level
parent->setLevel(Level::getWarn());
assertThresholdConsistent(parent);
assertThresholdConsistent(child1);
assertThresholdConsistent(child2);
assertThresholdConsistent(grandchild1);
assertThresholdConsistent(grandchild2);
assertThresholdIs(Level::getDebug(), child1);
assertThresholdIs(Level::getWarn(), child2);
assertThresholdIs(Level::getDebug(), grandchild1);
assertThresholdIs(Level::getWarn(), grandchild2);
}
// Additional Test 43: Alternating setLevel and changeParentTo calls
void testAlternatingSetLevelAndSetParent()
{
LoggerPtr p1 = hierarchy->getLogger(LOG4CXX_STR("p1"));
LoggerPtr p2 = hierarchy->getLogger(LOG4CXX_STR("p2"));
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("child"));
p1->setLevel(Level::getInfo());
assertThresholdConsistent(p1);
child->changeParentTo(p1);
assertThresholdConsistent(child);
assertThresholdIs(Level::getInfo(), child);
child->setLevel(Level::getDebug());
assertThresholdConsistent(child);
assertThresholdIs(Level::getDebug(), child);
p2->setLevel(Level::getWarn());
assertThresholdConsistent(p2);
child->changeParentTo(p2);
assertThresholdConsistent(child);
assertThresholdIs(Level::getDebug(), child); // Keeps own level
child->setLevel(LevelPtr());
assertThresholdConsistent(child);
assertThresholdIs(Level::getWarn(), child); // Now inherits from p2
child->changeParentTo(p1);
assertThresholdConsistent(child);
assertThresholdIs(Level::getInfo(), child); // Now inherits from p1
p1->setLevel(Level::getError());
assertThresholdConsistent(p1);
assertThresholdConsistent(child);
assertThresholdIs(Level::getError(), child);
}
// Additional Test 44: Verify threshold with OFF and ALL levels
void testOffAndAllLevels()
{
LoggerPtr parent = hierarchy->getLogger(LOG4CXX_STR("parent"));
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("parent.child"));
parent->setLevel(Level::getOff());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdIs(Level::getOff(), parent);
assertThresholdIs(Level::getOff(), child);
parent->setLevel(Level::getAll());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdIs(Level::getAll(), parent);
assertThresholdIs(Level::getAll(), child);
child->setLevel(Level::getOff());
assertThresholdConsistent(child);
assertThresholdIs(Level::getOff(), child);
parent->setLevel(Level::getTrace());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdIs(Level::getTrace(), parent);
assertThresholdIs(Level::getOff(), child); // Keeps OFF
}
// Additional Test 45: Complex scenario with provision nodes and level changes
void testComplexProvisionNodeScenario()
{
// Create deep child first
LoggerPtr deepChild = hierarchy->getLogger(LOG4CXX_STR("a.b.c.d.e.f.g"));
assertThresholdConsistent(deepChild);
LoggerPtr root = hierarchy->getRootLogger();
root->setLevel(Level::getFatal());
assertThresholdConsistent(deepChild);
assertThresholdIs(Level::getFatal(), deepChild);
// Create intermediate ancestors in random order
LoggerPtr c = hierarchy->getLogger(LOG4CXX_STR("a.b.c"));
c->setLevel(Level::getError());
assertThresholdConsistent(c);
assertThresholdConsistent(deepChild);
assertThresholdIs(Level::getError(), deepChild);
LoggerPtr a = hierarchy->getLogger(LOG4CXX_STR("a"));
a->setLevel(Level::getWarn());
assertThresholdConsistent(a);
assertThresholdConsistent(c);
assertThresholdConsistent(deepChild);
assertThresholdIs(Level::getWarn(), a);
assertThresholdIs(Level::getError(), c);
assertThresholdIs(Level::getError(), deepChild);
LoggerPtr e = hierarchy->getLogger(LOG4CXX_STR("a.b.c.d.e"));
e->setLevel(Level::getDebug());
assertThresholdConsistent(e);
assertThresholdConsistent(deepChild);
assertThresholdIs(Level::getDebug(), e);
assertThresholdIs(Level::getDebug(), deepChild);
LoggerPtr b = hierarchy->getLogger(LOG4CXX_STR("a.b"));
b->setLevel(Level::getInfo());
assertThresholdConsistent(b);
assertThresholdConsistent(c);
assertThresholdConsistent(e);
assertThresholdConsistent(deepChild);
assertThresholdIs(Level::getInfo(), b);
assertThresholdIs(Level::getError(), c);
assertThresholdIs(Level::getDebug(), e);
assertThresholdIs(Level::getDebug(), deepChild);
// Set e to null - deepChild should inherit from c
e->setLevel(LevelPtr());
assertThresholdConsistent(e);
assertThresholdConsistent(deepChild);
assertThresholdIs(Level::getError(), e);
assertThresholdIs(Level::getError(), deepChild);
}
// Additional Test 46: Multiple siblings with different levels
void testMultipleSiblingsWithDifferentLevels()
{
LoggerPtr parent = hierarchy->getLogger(LOG4CXX_STR("parent"));
parent->setLevel(Level::getInfo());
std::vector<LoggerPtr> siblings;
LevelPtr levels[] = {
Level::getTrace(),
Level::getDebug(),
LevelPtr(), // null - inherits
Level::getWarn(),
Level::getError(),
LevelPtr(), // null - inherits
Level::getFatal()
};
for (size_t i = 0; i < sizeof(levels)/sizeof(levels[0]); ++i)
{
std::ostringstream oss;
oss << "parent.sibling" << i;
LOG4CXX_DECODE_CHAR(category, oss.str());
LoggerPtr sibling = hierarchy->getLogger(category);
sibling->setLevel(levels[i]);
siblings.push_back(sibling);
assertThresholdConsistent(sibling);
}
// Verify each sibling has correct threshold
assertThresholdIs(Level::getTrace(), siblings[0]);
assertThresholdIs(Level::getDebug(), siblings[1]);
assertThresholdIs(Level::getInfo(), siblings[2]); // inherits
assertThresholdIs(Level::getWarn(), siblings[3]);
assertThresholdIs(Level::getError(), siblings[4]);
assertThresholdIs(Level::getInfo(), siblings[5]); // inherits
assertThresholdIs(Level::getFatal(), siblings[6]);
// Change parent level
parent->setLevel(Level::getDebug());
for (size_t i = 0; i < siblings.size(); ++i)
{
assertThresholdConsistent(siblings[i]);
}
// Only inheriting siblings should change
assertThresholdIs(Level::getTrace(), siblings[0]);
assertThresholdIs(Level::getDebug(), siblings[1]);
assertThresholdIs(Level::getDebug(), siblings[2]); // changed
assertThresholdIs(Level::getWarn(), siblings[3]);
assertThresholdIs(Level::getError(), siblings[4]);
assertThresholdIs(Level::getDebug(), siblings[5]); // changed
assertThresholdIs(Level::getFatal(), siblings[6]);
}
// Additional Test 47: Parent chain with gaps
void testParentChainWithGaps()
{
LoggerPtr root = hierarchy->getRootLogger();
root->setLevel(Level::getError());
// Create loggers with gaps in hierarchy
LoggerPtr level2 = hierarchy->getLogger(LOG4CXX_STR("a.b"));
LoggerPtr level5 = hierarchy->getLogger(LOG4CXX_STR("a.b.c.d.e"));
assertThresholdConsistent(level2);
assertThresholdConsistent(level5);
// Both should inherit from root
assertThresholdIs(Level::getError(), level2);
assertThresholdIs(Level::getError(), level5);
// Set level on level2
level2->setLevel(Level::getInfo());
assertThresholdConsistent(level2);
assertThresholdConsistent(level5);
// level5 should now inherit from level2
assertThresholdIs(Level::getInfo(), level5);
// Fill in a gap
LoggerPtr level3 = hierarchy->getLogger(LOG4CXX_STR("a.b.c"));
level3->setLevel(Level::getDebug());
assertThresholdConsistent(level3);
assertThresholdConsistent(level5);
// level5 should now inherit from level3
assertThresholdIs(Level::getDebug(), level5);
// Fill in another gap
LoggerPtr level4 = hierarchy->getLogger(LOG4CXX_STR("a.b.c.d"));
assertThresholdConsistent(level4);
assertThresholdConsistent(level5);
// level4 and level5 should inherit from level3
assertThresholdIs(Level::getDebug(), level4);
assertThresholdIs(Level::getDebug(), level5);
}
// Additional Test 48: Verify threshold after hierarchy reset
void testThresholdAfterHierarchyOperations()
{
LoggerPtr parent = hierarchy->getLogger(LOG4CXX_STR("parent"));
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("parent.child"));
parent->setLevel(Level::getInfo());
child->setLevel(Level::getDebug());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdIs(Level::getInfo(), parent);
assertThresholdIs(Level::getDebug(), child);
// After getting effective level, threshold should still be consistent
LevelPtr effectiveLevel = child->getEffectiveLevel();
assertThresholdConsistent(child);
assertThresholdIs(effectiveLevel, child);
}
// Additional Test 49: Cross-branch hierarchy changes
void testCrossBranchHierarchyChanges()
{
LoggerPtr root = hierarchy->getRootLogger();
root->setLevel(Level::getWarn());
// Branch A
LoggerPtr a = hierarchy->getLogger(LOG4CXX_STR("a"));
LoggerPtr ab = hierarchy->getLogger(LOG4CXX_STR("a.b"));
LoggerPtr abc = hierarchy->getLogger(LOG4CXX_STR("a.b.c"));
// Branch X
LoggerPtr x = hierarchy->getLogger(LOG4CXX_STR("x"));
LoggerPtr xy = hierarchy->getLogger(LOG4CXX_STR("x.y"));
LoggerPtr xyz = hierarchy->getLogger(LOG4CXX_STR("x.y.z"));
a->setLevel(Level::getInfo());
x->setLevel(Level::getDebug());
assertThresholdConsistent(a);
assertThresholdConsistent(ab);
assertThresholdConsistent(abc);
assertThresholdConsistent(x);
assertThresholdConsistent(xy);
assertThresholdConsistent(xyz);
assertThresholdIs(Level::getInfo(), ab);
assertThresholdIs(Level::getInfo(), abc);
assertThresholdIs(Level::getDebug(), xy);
assertThresholdIs(Level::getDebug(), xyz);
// Change root - should affect both branches (where not overridden)
root->setLevel(Level::getError());
assertThresholdConsistent(root);
assertThresholdConsistent(a);
assertThresholdConsistent(ab);
assertThresholdConsistent(abc);
assertThresholdConsistent(x);
assertThresholdConsistent(xy);
assertThresholdConsistent(xyz);
// Branch A still has its override
assertThresholdIs(Level::getInfo(), a);
assertThresholdIs(Level::getInfo(), ab);
assertThresholdIs(Level::getInfo(), abc);
// Branch X still has its override
assertThresholdIs(Level::getDebug(), x);
assertThresholdIs(Level::getDebug(), xy);
assertThresholdIs(Level::getDebug(), xyz);
// Set middle of branch A to null
a->setLevel(LevelPtr());
assertThresholdConsistent(a);
assertThresholdConsistent(ab);
assertThresholdConsistent(abc);
// Branch A should now inherit from root
assertThresholdIs(Level::getError(), a);
assertThresholdIs(Level::getError(), ab);
assertThresholdIs(Level::getError(), abc);
// Branch X should be unaffected
assertThresholdIs(Level::getDebug(), x);
assertThresholdIs(Level::getDebug(), xy);
assertThresholdIs(Level::getDebug(), xyz);
}
// Additional Test 50: Verify threshold with extremely deep hierarchy
void testExtremelyDeepHierarchy()
{
LoggerPtr root = hierarchy->getRootLogger();
root->setLevel(Level::getWarn());
std::string name = "level";
LoggerPtr previous = root;
std::vector<LoggerPtr> loggers;
// Create 50-level deep hierarchy
for (int i = 1; i <= 50; ++i)
{
std::ostringstream oss;
oss << name << '.' << i;
name = oss.str();
LOG4CXX_DECODE_CHAR(category, name);
LoggerPtr logger = hierarchy->getLogger(category);
loggers.push_back(logger);
assertThresholdConsistent(logger);
assertThresholdIs(Level::getWarn(), logger);
}
// Set level at depth 25
loggers[24]->setLevel(Level::getDebug());
// Verify all loggers
for (size_t i = 0; i < loggers.size(); ++i)
{
assertThresholdConsistent(loggers[i]);
if (i < 24)
{
assertThresholdIs(Level::getWarn(), loggers[i]);
}
else
{
assertThresholdIs(Level::getDebug(), loggers[i]);
}
}
// Set level at depth 40
loggers[39]->setLevel(Level::getTrace());
for (size_t i = 0; i < loggers.size(); ++i)
{
assertThresholdConsistent(loggers[i]);
if (i < 24)
{
assertThresholdIs(Level::getWarn(), loggers[i]);
}
else if (i < 39)
{
assertThresholdIs(Level::getDebug(), loggers[i]);
}
else
{
assertThresholdIs(Level::getTrace(), loggers[i]);
}
}
// Change root level
root->setLevel(Level::getError());
for (size_t i = 0; i < loggers.size(); ++i)
{
assertThresholdConsistent(loggers[i]);
if (i < 24)
{
assertThresholdIs(Level::getError(), loggers[i]);
}
else if (i < 39)
{
assertThresholdIs(Level::getDebug(), loggers[i]);
}
else
{
assertThresholdIs(Level::getTrace(), loggers[i]);
}
}
}
// Additional Test 51: Verify threshold consistency during logger retrieval
void testThresholdConsistencyDuringRetrieval()
{
LoggerPtr root = hierarchy->getRootLogger();
root->setLevel(Level::getInfo());
// Get logger multiple times and verify consistency each time
for (int i = 0; i < 10; ++i)
{
LoggerPtr logger = hierarchy->getLogger(LOG4CXX_STR("test.logger"));
assertThresholdConsistent(logger);
assertThresholdIs(Level::getInfo(), logger);
}
// Set level on the logger
LoggerPtr logger = hierarchy->getLogger(LOG4CXX_STR("test.logger"));
logger->setLevel(Level::getDebug());
// Get it again and verify
for (int i = 0; i < 10; ++i)
{
LoggerPtr sameLogger = hierarchy->getLogger(LOG4CXX_STR("test.logger"));
assertThresholdConsistent(sameLogger);
assertThresholdIs(Level::getDebug(), sameLogger);
}
}
// Additional Test 52: Threshold consistency with logger factory
void testThresholdConsistencyWithLoggerFactory()
{
LoggerPtr root = hierarchy->getRootLogger();
root->setLevel(Level::getWarn());
spi::LoggerFactoryPtr factory =
std::make_shared<spi::LoggerFactory>();
LoggerPtr logger1 = hierarchy->getLogger(LOG4CXX_STR("factory.test1"), factory);
LoggerPtr logger2 = hierarchy->getLogger(LOG4CXX_STR("factory.test2"), factory);
assertThresholdConsistent(logger1);
assertThresholdConsistent(logger2);
assertThresholdIs(Level::getWarn(), logger1);
assertThresholdIs(Level::getWarn(), logger2);
logger1->setLevel(Level::getDebug());
assertThresholdConsistent(logger1);
assertThresholdConsistent(logger2);
assertThresholdIs(Level::getDebug(), logger1);
assertThresholdIs(Level::getWarn(), logger2);
}
// Additional Test 53: Verify threshold after parent-child swap
void testThresholdAfterParentChildSwap()
{
LoggerPtr logger1 = hierarchy->getLogger(LOG4CXX_STR("swap.test1"));
LoggerPtr logger2 = hierarchy->getLogger(LOG4CXX_STR("swap.test2"));
logger1->setLevel(Level::getInfo());
logger2->setLevel(Level::getDebug());
assertThresholdConsistent(logger1);
assertThresholdConsistent(logger2);
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("child"));
// Set logger1 as parent
child->changeParentTo(logger1);
assertThresholdConsistent(child);
assertThresholdIs(Level::getInfo(), child);
// Swap to logger2 as parent
child->changeParentTo(logger2);
assertThresholdConsistent(child);
assertThresholdIs(Level::getDebug(), child);
// Swap back to logger1
child->changeParentTo(logger1);
assertThresholdConsistent(child);
assertThresholdIs(Level::getInfo(), child);
// Change logger1's level while it's the parent
logger1->setLevel(Level::getWarn());
assertThresholdConsistent(logger1);
assertThresholdConsistent(child);
assertThresholdIs(Level::getWarn(), child);
}
// Additional Test 54: Threshold with all levels set to same value
void testThresholdWithAllSameLevel()
{
LoggerPtr root = hierarchy->getRootLogger();
LoggerPtr a = hierarchy->getLogger(LOG4CXX_STR("a"));
LoggerPtr ab = hierarchy->getLogger(LOG4CXX_STR("a.b"));
LoggerPtr abc = hierarchy->getLogger(LOG4CXX_STR("a.b.c"));
// Set all to same level
LevelPtr sameLevel = Level::getInfo();
root->setLevel(sameLevel);
a->setLevel(sameLevel);
ab->setLevel(sameLevel);
abc->setLevel(sameLevel);
assertThresholdConsistent(root);
assertThresholdConsistent(a);
assertThresholdConsistent(ab);
assertThresholdConsistent(abc);
assertThresholdIs(Level::getInfo(), root);
assertThresholdIs(Level::getInfo(), a);
assertThresholdIs(Level::getInfo(), ab);
assertThresholdIs(Level::getInfo(), abc);
// Set middle one to null - should still be INFO
ab->setLevel(LevelPtr());
assertThresholdConsistent(ab);
assertThresholdIs(Level::getInfo(), ab);
}
// Additional Test 55: Threshold after rapid parent reassignments
void testThresholdAfterRapidParentReassignments()
{
LoggerPtr p1 = hierarchy->getLogger(LOG4CXX_STR("p1"));
LoggerPtr p2 = hierarchy->getLogger(LOG4CXX_STR("p2"));
LoggerPtr p3 = hierarchy->getLogger(LOG4CXX_STR("p3"));
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("child"));
p1->setLevel(Level::getTrace());
p2->setLevel(Level::getDebug());
p3->setLevel(Level::getInfo());
for (int i = 0; i < 100; ++i)
{
child->changeParentTo(p1);
assertThresholdConsistent(child);
assertThresholdIs(Level::getTrace(), child);
child->changeParentTo(p2);
assertThresholdConsistent(child);
assertThresholdIs(Level::getDebug(), child);
child->changeParentTo(p3);
assertThresholdConsistent(child);
assertThresholdIs(Level::getInfo(), child);
}
}
// Additional Test 56: Threshold with zigzag level pattern
void testThresholdWithZigzagLevelPattern()
{
LoggerPtr root = hierarchy->getRootLogger();
LoggerPtr l1 = hierarchy->getLogger(LOG4CXX_STR("a"));
LoggerPtr l2 = hierarchy->getLogger(LOG4CXX_STR("a.b"));
LoggerPtr l3 = hierarchy->getLogger(LOG4CXX_STR("a.b.c"));
LoggerPtr l4 = hierarchy->getLogger(LOG4CXX_STR("a.b.c.d"));
LoggerPtr l5 = hierarchy->getLogger(LOG4CXX_STR("a.b.c.d.e"));
// Set zigzag pattern: high, low, high, low, high
root->setLevel(Level::getError()); // high
l1->setLevel(Level::getDebug()); // low
l2->setLevel(Level::getWarn()); // high
l3->setLevel(Level::getTrace()); // low
l4->setLevel(Level::getFatal()); // high
assertThresholdConsistent(root);
assertThresholdConsistent(l1);
assertThresholdConsistent(l2);
assertThresholdConsistent(l3);
assertThresholdConsistent(l4);
assertThresholdConsistent(l5);
assertThresholdIs(Level::getError(), root);
assertThresholdIs(Level::getDebug(), l1);
assertThresholdIs(Level::getWarn(), l2);
assertThresholdIs(Level::getTrace(), l3);
assertThresholdIs(Level::getFatal(), l4);
assertThresholdIs(Level::getFatal(), l5); // inherits from l4
}
// Additional Test 57: Threshold after removing and re-adding levels
void testThresholdAfterRemovingAndReaddingLevels()
{
LoggerPtr parent = hierarchy->getLogger(LOG4CXX_STR("parent"));
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("parent.child"));
LoggerPtr grandchild = hierarchy->getLogger(LOG4CXX_STR("parent.child.grandchild"));
parent->setLevel(Level::getWarn());
child->setLevel(Level::getDebug());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
assertThresholdIs(Level::getWarn(), parent);
assertThresholdIs(Level::getDebug(), child);
assertThresholdIs(Level::getDebug(), grandchild);
// Remove child's level
child->setLevel(LevelPtr());
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
assertThresholdIs(Level::getWarn(), child);
assertThresholdIs(Level::getWarn(), grandchild);
// Re-add child's level
child->setLevel(Level::getInfo());
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
assertThresholdIs(Level::getInfo(), child);
assertThresholdIs(Level::getInfo(), grandchild);
// Remove parent's level
parent->setLevel(LevelPtr());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
// Parent should inherit from root, child keeps its level
LoggerPtr root = hierarchy->getRootLogger();
assertThresholdIs(root->getEffectiveLevel(), parent);
assertThresholdIs(Level::getInfo(), child);
assertThresholdIs(Level::getInfo(), grandchild);
// Re-add parent's level
parent->setLevel(Level::getError());
assertThresholdConsistent(parent);
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
assertThresholdIs(Level::getError(), parent);
assertThresholdIs(Level::getInfo(), child);
assertThresholdIs(Level::getInfo(), grandchild);
}
// Additional Test 58: Threshold consistency with diamond-shaped hierarchy
void testThresholdWithDiamondHierarchy()
{
LoggerPtr root = hierarchy->getRootLogger();
root->setLevel(Level::getError());
// Create diamond pattern
LoggerPtr top = hierarchy->getLogger(LOG4CXX_STR("top"));
LoggerPtr left = hierarchy->getLogger(LOG4CXX_STR("top.left"));
LoggerPtr right = hierarchy->getLogger(LOG4CXX_STR("top.right"));
LoggerPtr bottom = hierarchy->getLogger(LOG4CXX_STR("top.left.bottom"));
// Note: bottom can only have one parent in the hierarchy
// It will be under "top.left" by its name
top->setLevel(Level::getWarn());
left->setLevel(Level::getInfo());
right->setLevel(Level::getDebug());
assertThresholdConsistent(root);
assertThresholdConsistent(top);
assertThresholdConsistent(left);
assertThresholdConsistent(right);
assertThresholdConsistent(bottom);
assertThresholdIs(Level::getWarn(), top);
assertThresholdIs(Level::getInfo(), left);
assertThresholdIs(Level::getDebug(), right);
assertThresholdIs(Level::getInfo(), bottom); // inherits from left
// Change top level
top->setLevel(Level::getTrace());
assertThresholdConsistent(top);
assertThresholdConsistent(left);
assertThresholdConsistent(right);
assertThresholdConsistent(bottom);
// left, right, and bottom should keep their levels
assertThresholdIs(Level::getTrace(), top);
assertThresholdIs(Level::getInfo(), left);
assertThresholdIs(Level::getDebug(), right);
assertThresholdIs(Level::getInfo(), bottom);
}
// Additional Test 59: Threshold with very long logger names
void testThresholdWithVeryLongLoggerNames()
{
LogString longName = LOG4CXX_STR("very.long.logger.name.with.many.segments.to.test.the.hierarchy");
longName += LOG4CXX_STR(".and.even.more.segments.to.make.it.really.long.and.complex");
longName += LOG4CXX_STR(".final.segment.at.the.end");
LoggerPtr logger = hierarchy->getLogger(longName);
assertThresholdConsistent(logger);
LoggerPtr root = hierarchy->getRootLogger();
root->setLevel(Level::getInfo());
assertThresholdConsistent(logger);
assertThresholdIs(Level::getInfo(), logger);
// Set level on intermediate ancestor
LoggerPtr intermediate = hierarchy->getLogger(LOG4CXX_STR("very.long.logger.name.with.many"));
intermediate->setLevel(Level::getDebug());
assertThresholdConsistent(intermediate);
assertThresholdConsistent(logger);
assertThresholdIs(Level::getDebug(), logger);
// Set level on the long logger itself
logger->setLevel(Level::getWarn());
assertThresholdConsistent(logger);
assertThresholdIs(Level::getWarn(), logger);
}
// Additional Test 60: Threshold after setting same level multiple times
void testThresholdAfterSettingSameLevelMultipleTimes()
{
LoggerPtr logger = hierarchy->getLogger(LOG4CXX_STR("test"));
for (int i = 0; i < 50; ++i)
{
logger->setLevel(Level::getInfo());
assertThresholdConsistent(logger);
assertThresholdIs(Level::getInfo(), logger);
}
logger->setLevel(Level::getDebug());
assertThresholdConsistent(logger);
assertThresholdIs(Level::getDebug(), logger);
for (int i = 0; i < 50; ++i)
{
logger->setLevel(Level::getDebug());
assertThresholdConsistent(logger);
assertThresholdIs(Level::getDebug(), logger);
}
}
// Additional Test 61: Complex scenario mixing all operations
void testComplexMixedOperations()
{
LoggerPtr root = hierarchy->getRootLogger();
root->setLevel(Level::getWarn());
// Create loggers in mixed order
LoggerPtr deep = hierarchy->getLogger(LOG4CXX_STR("a.b.c.d.e.f"));
assertThresholdConsistent(deep);
LoggerPtr mid = hierarchy->getLogger(LOG4CXX_STR("a.b.c"));
mid->setLevel(Level::getInfo());
assertThresholdConsistent(mid);
assertThresholdConsistent(deep);
LoggerPtr top = hierarchy->getLogger(LOG4CXX_STR("a"));
top->setLevel(Level::getError());
assertThresholdConsistent(top);
assertThresholdConsistent(mid);
assertThresholdConsistent(deep);
assertThresholdIs(Level::getError(), top);
assertThresholdIs(Level::getInfo(), mid);
assertThresholdIs(Level::getInfo(), deep);
// Set deep's level
deep->setLevel(Level::getDebug());
assertThresholdConsistent(deep);
assertThresholdIs(Level::getDebug(), deep);
// Create sibling
LoggerPtr sibling = hierarchy->getLogger(LOG4CXX_STR("a.b.c.d.e.g"));
assertThresholdConsistent(sibling);
assertThresholdIs(Level::getInfo(), sibling);
// Change mid to null
mid->setLevel(LevelPtr());
assertThresholdConsistent(mid);
assertThresholdConsistent(deep);
assertThresholdConsistent(sibling);
assertThresholdIs(Level::getError(), mid);
assertThresholdIs(Level::getDebug(), deep);
assertThresholdIs(Level::getError(), sibling);
// Change top
top->setLevel(Level::getTrace());
assertThresholdConsistent(top);
assertThresholdConsistent(mid);
assertThresholdConsistent(deep);
assertThresholdConsistent(sibling);
assertThresholdIs(Level::getTrace(), top);
assertThresholdIs(Level::getTrace(), mid);
assertThresholdIs(Level::getDebug(), deep);
assertThresholdIs(Level::getTrace(), sibling);
// Create intermediate logger
LoggerPtr intermediate = hierarchy->getLogger(LOG4CXX_STR("a.b"));
intermediate->setLevel(Level::getFatal());
assertThresholdConsistent(intermediate);
assertThresholdConsistent(mid);
assertThresholdConsistent(deep);
assertThresholdConsistent(sibling);
assertThresholdIs(Level::getFatal(), intermediate);
assertThresholdIs(Level::getFatal(), mid);
assertThresholdIs(Level::getDebug(), deep);
assertThresholdIs(Level::getFatal(), sibling);
}
// Additional Test 62: Threshold after parent change with grandchildren
void testThresholdAfterParentChangeWithGrandchildren()
{
LoggerPtr p1 = hierarchy->getLogger(LOG4CXX_STR("p1"));
LoggerPtr p2 = hierarchy->getLogger(LOG4CXX_STR("p2"));
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("child"));
LoggerPtr grandchild = hierarchy->getLogger(LOG4CXX_STR("child.grandchild"));
LoggerPtr greatGrandchild = hierarchy->getLogger(LOG4CXX_STR("child.grandchild.great"));
p1->setLevel(Level::getInfo());
p2->setLevel(Level::getError());
child->changeParentTo(p1);
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
assertThresholdConsistent(greatGrandchild);
assertThresholdIs(Level::getInfo(), child);
assertThresholdIs(Level::getInfo(), grandchild);
assertThresholdIs(Level::getInfo(), greatGrandchild);
// Change parent - all descendants should update
child->changeParentTo(p2);
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
assertThresholdConsistent(greatGrandchild);
assertThresholdIs(Level::getError(), child);
assertThresholdIs(Level::getError(), grandchild);
assertThresholdIs(Level::getError(), greatGrandchild);
// Set grandchild's level
grandchild->setLevel(Level::getDebug());
assertThresholdConsistent(grandchild);
assertThresholdConsistent(greatGrandchild);
assertThresholdIs(Level::getDebug(), grandchild);
assertThresholdIs(Level::getDebug(), greatGrandchild);
// Change child's parent again - grandchild should keep its level
child->changeParentTo(p1);
assertThresholdConsistent(child);
assertThresholdConsistent(grandchild);
assertThresholdConsistent(greatGrandchild);
assertThresholdIs(Level::getInfo(), child);
assertThresholdIs(Level::getDebug(), grandchild);
assertThresholdIs(Level::getDebug(), greatGrandchild);
}
// Additional Test 63: Verify threshold with empty logger name
void testThresholdWithEmptyLoggerName()
{
// Root logger has empty name
LoggerPtr root = hierarchy->getRootLogger();
root->setLevel(Level::getInfo());
assertThresholdConsistent(root);
assertThresholdIs(Level::getInfo(), root);
LoggerPtr child = hierarchy->getLogger(LOG4CXX_STR("child"));
assertThresholdConsistent(child);
assertThresholdIs(Level::getInfo(), child);
}
// Additional Test 64: Threshold with single character logger names
void testThresholdWithSingleCharacterNames()
{
LoggerPtr a = hierarchy->getLogger(LOG4CXX_STR("a"));
LoggerPtr ab = hierarchy->getLogger(LOG4CXX_STR("a.b"));
LoggerPtr abc = hierarchy->getLogger(LOG4CXX_STR("a.b.c"));
LoggerPtr abcd = hierarchy->getLogger(LOG4CXX_STR("a.b.c.d"));
a->setLevel(Level::getWarn());
assertThresholdConsistent(a);
assertThresholdConsistent(ab);
assertThresholdConsistent(abc);
assertThresholdConsistent(abcd);
assertThresholdIs(Level::getWarn(), ab);
assertThresholdIs(Level::getWarn(), abc);
assertThresholdIs(Level::getWarn(), abcd);
abc->setLevel(Level::getDebug());
assertThresholdConsistent(abc);
assertThresholdConsistent(abcd);
assertThresholdIs(Level::getDebug(), abc);
assertThresholdIs(Level::getDebug(), abcd);
}
// Additional Test 65: Final comprehensive stress test
void testFinalComprehensiveStressTest()
{
LoggerPtr root = hierarchy->getRootLogger();
std::vector<LoggerPtr> allLoggers;
// Create complex hierarchy
std::string bases[] = {"com", "org", "net", "edu"};
std::string mids[] = {"example", "apache", "test", "demo"};
std::string ends[] = {"app", "service", "module", "component"};
for (size_t i = 0; i < sizeof(bases)/sizeof(bases[0]); ++i)
{
for (size_t j = 0; j < sizeof(mids)/sizeof(mids[0]); ++j)
{
for (size_t k = 0; k < sizeof(ends)/sizeof(ends[0]); ++k)
{
std::ostringstream oss;
oss << bases[i] << "." << mids[j] << "." << ends[k];
LOG4CXX_DECODE_CHAR(category, oss.str());
LoggerPtr logger = hierarchy->getLogger(category);
allLoggers.push_back(logger);
}
}
}
// Set root level
root->setLevel(Level::getWarn());
// Verify all loggers
for (size_t i = 0; i < allLoggers.size(); ++i)
{
assertThresholdConsistent(allLoggers[i]);
assertThresholdIs(Level::getWarn(), allLoggers[i]);
}
// Set levels on some base loggers
LoggerPtr com = hierarchy->getLogger(LOG4CXX_STR("com"));
LoggerPtr org = hierarchy->getLogger(LOG4CXX_STR("org"));
com->setLevel(Level::getInfo());
org->setLevel(Level::getDebug());
// Verify all loggers again
for (size_t i = 0; i < allLoggers.size(); ++i)
{
assertThresholdConsistent(allLoggers[i]);
}
// Set levels on some mid-level loggers
LoggerPtr comExample = hierarchy->getLogger(LOG4CXX_STR("com.example"));
LoggerPtr orgApache = hierarchy->getLogger(LOG4CXX_STR("org.apache"));
comExample->setLevel(Level::getTrace());
orgApache->setLevel(Level::getError());
// Verify all loggers again
for (size_t i = 0; i < allLoggers.size(); ++i)
{
assertThresholdConsistent(allLoggers[i]);
}
// Set some to null
com->setLevel(LevelPtr());
// Verify all loggers again
for (size_t i = 0; i < allLoggers.size(); ++i)
{
assertThresholdConsistent(allLoggers[i]);
}
// Change root level
root->setLevel(Level::getFatal());
// Final verification
for (size_t i = 0; i < allLoggers.size(); ++i)
{
assertThresholdConsistent(allLoggers[i]);
}
// Verify specific expected values
LoggerPtr comExampleApp = hierarchy->getLogger(LOG4CXX_STR("com.example.app"));
assertThresholdConsistent(comExampleApp);
assertThresholdIs(Level::getTrace(), comExampleApp);
LoggerPtr orgApacheTest = hierarchy->getLogger(LOG4CXX_STR("org.apache.test"));
assertThresholdConsistent(orgApacheTest);
assertThresholdIs(Level::getError(), orgApacheTest);
LoggerPtr netExampleApp = hierarchy->getLogger(LOG4CXX_STR("net.example.app"));
assertThresholdConsistent(netExampleApp);
assertThresholdIs(Level::getFatal(), netExampleApp);
}
};
LOGUNIT_TEST_SUITE_REGISTRATION(LoggerThresholdConsistencyTest);