Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test logging interface #463

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

enigbe
Copy link
Contributor

@enigbe enigbe commented Feb 10, 2025

What this PR does

This is another follow-up PR to #407 where we test the log facade and custom logging interfaces.

It follows an earlier conversation to address testing without explicitly configuring the logger in all test cases.

cc @tnull

- `TestConfig` wraps `Config` and other fields, specifically
a log-related field that can be over-written on a per-test
basis.
- With `TestConfig`, we can maintain the general testing
setup/APIs as is and only modify fields based on specific
features we want to test.
@enigbe enigbe force-pushed the 2025-02-test-logging-interface branch from da2edcc to d85c5c5 Compare February 10, 2025 14:27
Copy link
Collaborator

@tnull tnull left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

pub log_writer: TestLogWriter,
}

impl Default for TestConfig {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for this impl, just add Default to the derive above.

@@ -251,6 +253,34 @@ pub(crate) enum TestChainSource<'a> {
BitcoindRpc(&'a BitcoinD),
}

#[derive(Clone)]
pub(crate) enum TestLogWriter {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While TestConfig could have some general utility going forward, I'm not quite convinced we need all this boilerplate just to switch the logger in a one-off test. We could at least simplify this enum, no?

@@ -237,7 +239,7 @@ pub(crate) fn random_config(anchor_channels: bool) -> Config {
println!("Setting random LDK node alias: {:?}", alias);
config.node_alias = alias;

config
TestConfig { node_config: config, log_writer: TestLogWriter::default() }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using this type of struct construction:

	TestConfig { node_config, ..Default::default() }

@@ -215,7 +217,7 @@ pub(crate) fn random_node_alias() -> Option<NodeAlias> {
Some(NodeAlias(bytes))
}

pub(crate) fn random_config(anchor_channels: bool) -> Config {
pub(crate) fn random_config(anchor_channels: bool) -> TestConfig {
let mut config = Config::default();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: if we're already renaming the field, let's name this node_config for consistency.

@@ -39,12 +40,13 @@ use bitcoincore_rpc::RpcApi;
use electrsd::{bitcoind, bitcoind::BitcoinD, ElectrsD};
use electrum_client::ElectrumApi;

use log::{Level, LevelFilter, Log, Record};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to be confusing. Can we possibly move these mock logger to a dedicated tests/common/logging.rs or similar? Also let's rename via .. as .. all of these imports to make it clear which version of Level etc. they are referring to (as we have at least 3 or 4 of them floating around now). I.e.

use log::Level as LogFacadeLevel;
..

@@ -1207,3 +1209,90 @@ impl KVStore for TestSyncStore {
self.do_list(primary_namespace, secondary_namespace)
}
}

pub(crate) struct MockLogger {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's name this MockLogFacadeLogger for now.

}

struct MockLogRecord<'a>(LogRecord<'a>);
struct MockLogLevel(LogLevel);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need these newtypes?

pub(crate) fn init_log_logger(level: LevelFilter) -> Arc<MockLogger> {
let logger = Arc::new(MockLogger::new());
log::set_boxed_logger(Box::new(logger.clone())).unwrap();
log::set_max_level(level);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, if this is part of the log API anyways, should we drop our max_log_level value in the log facade related builder methods and LogWriter variants? Do you have an opinion here? Do we gain much by also limiting on our end?


let logger = init_log_logger(LevelFilter::Trace);
let mut config = random_config(false);
config.log_writer = TestLogWriter::LogFacade { max_log_level: LogLevel::Gossip };
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above, a bit awkward that we have an additional filter on the level.

let _node = setup_node(&chain_source, config, None);
println!("== Facade logging end ==");

assert!(!logger.retrieve_logs().is_empty());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we do more checks to ensure the messages contain something valid (or even check the structure, certain fields, etc?), rather than doing all this work just to check the Vec isn't empty?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants