From 770d5631cded284a101053f580aa7051d391002a Mon Sep 17 00:00:00 2001 From: Bowen Ho Date: Sat, 13 Jun 2026 15:52:30 +0800 Subject: [PATCH] Fix tests error log by enabling LogPlugin only once When running tests, there are many: ``` ERROR bevy_log: Could not set global logger and tracing subscriber as they are already set. Consider disabling LogPlugin. ``` Because tests usually run in the same context, but each test tries to set logger and tracing subscriber, which should be only set once in a context. This commit takes the approach of only setting up [LogPlugin] once in the whole test run, rather than removing [LogPlugin] entirely for all test apps. Although there are no logs in Valence's existing tests currently, keeping the logger available is useful for debugging single tests in the future. Also note by calling `testing::add_plugins`, `example_test_server_tick_increment()` and `idle_update` now disables [NetworkPlugin], which should be okay in these tests. Ref --- benches/idle.rs | 4 ++-- benches/many_players.rs | 8 +++----- src/testing.rs | 35 ++++++++++++++++++++++++++++++++--- src/tests/example.rs | 7 +++---- 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/benches/idle.rs b/benches/idle.rs index a563b832e..18dfaea21 100644 --- a/benches/idle.rs +++ b/benches/idle.rs @@ -1,5 +1,5 @@ use divan::Bencher; -use valence::prelude::*; +use valence::{prelude::*, testing}; /// Benches the performance of a single server tick while nothing much is /// happening. @@ -7,7 +7,7 @@ use valence::prelude::*; pub(crate) fn idle_update(bencher: Bencher) { let mut app = App::new(); - app.add_plugins(DefaultPlugins); + testing::add_plugins(&mut app); app.add_systems(Startup, setup); // Run startup schedule. diff --git a/benches/many_players.rs b/benches/many_players.rs index 76eadc400..f69bd2bd9 100644 --- a/benches/many_players.rs +++ b/benches/many_players.rs @@ -8,11 +8,10 @@ use valence::keepalive::KeepaliveSettings; use valence::layer::chunk::UnloadedChunk; use valence::layer::LayerBundle; use valence::math::DVec3; -use valence::network::NetworkPlugin; use valence::protocol::packets::play::{FullC2s, HandSwingC2s}; use valence::registry::{BiomeRegistry, DimensionTypeRegistry}; -use valence::testing::create_mock_client; -use valence::{ident, ChunkPos, DefaultPlugins, Hand, Server, ServerSettings}; +use valence::testing::{self, create_mock_client}; +use valence::{ident, ChunkPos, Hand, Server, ServerSettings}; use valence_server::CompressionThreshold; #[divan::bench] @@ -37,8 +36,7 @@ fn run_many_players(bencher: Bencher, client_count: usize, view_dist: u8, world_ period: Duration::MAX, }); - app.add_plugins(DefaultPlugins.build().disable::()); - + testing::add_plugins(&mut app); app.update(); // Initialize plugins. let mut layer = LayerBundle::new( diff --git a/src/testing.rs b/src/testing.rs index fb3ac64c2..914a44eb5 100644 --- a/src/testing.rs +++ b/src/testing.rs @@ -1,10 +1,11 @@ use std::collections::VecDeque; use std::net::{IpAddr, Ipv4Addr}; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, Mutex, Once}; use std::time::{Duration, Instant}; use bevy_app::prelude::*; use bevy_ecs::prelude::*; +use bevy_log::LogPlugin; use bytes::{Buf, BufMut, BytesMut}; use uuid::Uuid; use valence_ident::ident; @@ -18,6 +19,34 @@ use valence_server::protocol::{Decode, Encode, Packet, PacketDecoder, PacketEnco use valence_server::{ChunkLayer, EntityLayer, Server, ServerSettings}; use crate::DefaultPlugins; + +/// Add plugins to `app` with [`NetworkPlugin`] disabled. +/// +/// Also, for tests usually run in the same context, the +/// logger and the subscriber in [`LogPlugin`] should only +/// be initialized once. So only the first test executing +/// this will have [`LogPlugin`] enabled. Other tests will +/// have [`LogPlugin`] disabled. +pub fn add_plugins(app: &mut App) { + static ONCE: Once = Once::new(); + let mut is_first = false; + + ONCE.call_once(|| { + is_first = true; + }); + + let plugins = if is_first { + DefaultPlugins.build().disable::() + } else { + DefaultPlugins + .build() + .disable::() + .disable::() + }; + + app.add_plugins(plugins); +} + pub struct ScenarioSingleClient { /// The new bevy application. pub app: App, @@ -43,9 +72,9 @@ impl ScenarioSingleClient { .insert_resource(ServerSettings { compression_threshold: Default::default(), ..Default::default() - }) - .add_plugins(DefaultPlugins.build().disable::()); + }); + add_plugins(&mut app); app.update(); // Initialize plugins. let chunk_layer = ChunkLayer::new( diff --git a/src/tests/example.rs b/src/tests/example.rs index 7560cf56f..138145620 100644 --- a/src/tests/example.rs +++ b/src/tests/example.rs @@ -12,15 +12,14 @@ use crate::entity::Position; use crate::inventory::{Inventory, InventoryKind, OpenInventory}; use crate::math::DVec3; use crate::protocol::packets::play::{InventoryS2c, OpenScreenS2c, PositionAndOnGroundC2s}; -use crate::testing::ScenarioSingleClient; -use crate::{DefaultPlugins, Server}; +use crate::testing::{self, ScenarioSingleClient}; +use crate::Server; /// The server's tick should increment every update. #[test] fn example_test_server_tick_increment() { let mut app = App::new(); - - app.add_plugins(DefaultPlugins); + testing::add_plugins(&mut app); let tick = app.world_mut().resource::().current_tick();