Skip to content

Commit a7b1ce4

Browse files
committed
Rewrite asset processing tests to allow adding sources piecemeal.
1 parent 47ceeb0 commit a7b1ce4

File tree

1 file changed

+95
-110
lines changed

1 file changed

+95
-110
lines changed

crates/bevy_asset/src/processor/tests.rs

Lines changed: 95 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@ use alloc::{
77
vec::Vec,
88
};
99
use async_lock::{RwLock, RwLockWriteGuard};
10-
use bevy_platform::{
11-
collections::HashMap,
12-
sync::{Mutex, PoisonError},
13-
};
10+
use atomicow::CowArc;
11+
use bevy_platform::sync::{Mutex, PoisonError};
1412
use bevy_reflect::TypePath;
1513
use core::marker::PhantomData;
1614
use futures_lite::AsyncWriteExt;
@@ -25,8 +23,8 @@ use bevy_tasks::BoxedFuture;
2523
use crate::{
2624
io::{
2725
memory::{Dir, MemoryAssetReader, MemoryAssetWriter},
28-
AssetReader, AssetReaderError, AssetSourceBuilder, AssetSourceEvent, AssetSourceId,
29-
AssetWatcher, PathStream, Reader,
26+
AssetReader, AssetReaderError, AssetSourceBuilder, AssetSourceEvent, AssetWatcher,
27+
PathStream, Reader,
3028
},
3129
processor::{
3230
AssetProcessor, LoadTransformAndSave, LogEntry, ProcessorState, ProcessorTransactionLog,
@@ -35,7 +33,8 @@ use crate::{
3533
saver::AssetSaver,
3634
tests::{run_app_until, CoolText, CoolTextLoader, CoolTextRon, SubText},
3735
transformer::{AssetTransformer, TransformedAsset},
38-
Asset, AssetApp, AssetLoader, AssetMode, AssetPath, AssetPlugin, LoadContext,
36+
Asset, AssetApp, AssetLoader, AssetMode, AssetPath, AssetPlugin, DefaultAssetSource,
37+
LoadContext,
3938
};
4039

4140
#[derive(Clone)]
@@ -49,7 +48,6 @@ struct AppWithProcessor {
4948
app: App,
5049
source_gate: Arc<RwLock<()>>,
5150
default_source_dirs: ProcessingDirs,
52-
extra_sources_dirs: HashMap<String, ProcessingDirs>,
5351
}
5452

5553
/// Similar to [`crate::io::gated::GatedReader`], but uses a lock instead of a channel to avoid
@@ -107,94 +105,83 @@ fn serialize_as_cool_text(text: &str) -> String {
107105
ron::ser::to_string_pretty(&cool_text_ron, PrettyConfig::new().new_line("\n")).unwrap()
108106
}
109107

110-
fn create_app_with_asset_processor(extra_sources: &[String]) -> AppWithProcessor {
111-
let mut app = App::new();
112-
let source_gate = Arc::new(RwLock::new(()));
113-
114-
struct UnfinishedProcessingDirs {
115-
source: Dir,
116-
processed: Dir,
117-
// The receiver channel for the source event sender for the unprocessed source.
118-
source_event_sender_receiver:
119-
async_channel::Receiver<async_channel::Sender<AssetSourceEvent>>,
120-
}
108+
/// The processing dirs that need to be "finished" before being used.
109+
struct UnfinishedProcessingDirs {
110+
/// The directory of the source assets.
111+
source: Dir,
112+
/// The directory of the processed assets.
113+
processed: Dir,
114+
/// The receiver channel for the source event sender for the unprocessed source.
115+
source_event_sender_receiver: async_channel::Receiver<async_channel::Sender<AssetSourceEvent>>,
116+
}
121117

122-
impl UnfinishedProcessingDirs {
123-
fn finish(self) -> ProcessingDirs {
124-
ProcessingDirs {
125-
source: self.source,
126-
processed: self.processed,
127-
// The processor listens for events on the source unconditionally, and we enable
128-
// watching for the processed source, so both of these channels will be filled.
129-
source_event_sender: self.source_event_sender_receiver.recv_blocking().unwrap(),
130-
}
118+
impl UnfinishedProcessingDirs {
119+
/// Attempts to finish the source by fetching the source event sender.
120+
///
121+
/// This will block if called before adding the source.
122+
fn finish(self) -> ProcessingDirs {
123+
ProcessingDirs {
124+
source: self.source,
125+
processed: self.processed,
126+
// The processor listens for events on the source unconditionally, and we enable
127+
// watching for the processed source, so both of these channels will be filled.
128+
source_event_sender: self.source_event_sender_receiver.recv_blocking().unwrap(),
131129
}
132130
}
131+
}
133132

134-
fn create_source(
135-
app: &mut App,
136-
source_id: AssetSourceId<'static>,
137-
source_gate: Arc<RwLock<()>>,
138-
) -> UnfinishedProcessingDirs {
139-
let source_dir = Dir::default();
140-
let processed_dir = Dir::default();
133+
/// Creates a source, including its processed and unprocessed directories, gated on `source_gate`.
134+
fn create_source(source_gate: Arc<RwLock<()>>) -> (AssetSourceBuilder, UnfinishedProcessingDirs) {
135+
let source_dir = Dir::default();
136+
let processed_dir = Dir::default();
141137

142-
let source_memory_reader = LockGatedReader::new(
143-
source_gate,
144-
MemoryAssetReader {
145-
root: source_dir.clone(),
146-
},
147-
);
148-
let processed_memory_reader = MemoryAssetReader {
149-
root: processed_dir.clone(),
150-
};
151-
let processed_memory_writer = MemoryAssetWriter {
152-
root: processed_dir.clone(),
153-
};
138+
let source_memory_reader = LockGatedReader::new(
139+
source_gate,
140+
MemoryAssetReader {
141+
root: source_dir.clone(),
142+
},
143+
);
144+
let processed_memory_reader = MemoryAssetReader {
145+
root: processed_dir.clone(),
146+
};
147+
let processed_memory_writer = MemoryAssetWriter {
148+
root: processed_dir.clone(),
149+
};
154150

155-
let (source_event_sender_sender, source_event_sender_receiver) = async_channel::bounded(1);
151+
let (source_event_sender_sender, source_event_sender_receiver) = async_channel::bounded(1);
156152

157-
struct FakeWatcher;
153+
struct FakeWatcher;
158154

159-
impl AssetWatcher for FakeWatcher {}
155+
impl AssetWatcher for FakeWatcher {}
160156

161-
app.register_asset_source(
162-
source_id,
163-
AssetSourceBuilder::new(move || Box::new(source_memory_reader.clone()))
164-
.with_watcher(move |sender: async_channel::Sender<AssetSourceEvent>| {
165-
source_event_sender_sender.send_blocking(sender).unwrap();
166-
Some(Box::new(FakeWatcher))
167-
})
168-
.with_processed_reader(move || Box::new(processed_memory_reader.clone()))
169-
.with_processed_writer(move |_| Some(Box::new(processed_memory_writer.clone()))),
170-
);
157+
let source_builder = AssetSourceBuilder::new(move || Box::new(source_memory_reader.clone()))
158+
.with_watcher(move |sender: async_channel::Sender<AssetSourceEvent>| {
159+
source_event_sender_sender.send_blocking(sender).unwrap();
160+
Some(Box::new(FakeWatcher))
161+
})
162+
.with_processed_reader(move || Box::new(processed_memory_reader.clone()))
163+
.with_processed_writer(move |_| Some(Box::new(processed_memory_writer.clone())));
171164

165+
(
166+
source_builder,
172167
UnfinishedProcessingDirs {
173168
source: source_dir,
174169
processed: processed_dir,
175170
source_event_sender_receiver,
176-
}
177-
}
171+
},
172+
)
173+
}
178174

179-
let default_source_dirs = create_source(&mut app, AssetSourceId::Default, source_gate.clone());
180-
181-
let extra_sources_dirs = extra_sources
182-
.iter()
183-
.map(|source_name| {
184-
(
185-
source_name.clone(),
186-
create_source(
187-
&mut app,
188-
AssetSourceId::Name(source_name.clone().into()),
189-
source_gate.clone(),
190-
),
191-
)
192-
})
193-
.collect::<Vec<_>>();
175+
fn create_app_with_asset_processor() -> AppWithProcessor {
176+
let mut app = App::new();
177+
let source_gate = Arc::new(RwLock::new(()));
178+
179+
let (default_source_builder, default_source_dirs) = create_source(source_gate.clone());
194180

195181
app.add_plugins((
196182
TaskPoolPlugin::default(),
197183
AssetPlugin {
184+
default_source: DefaultAssetSource::FromBuilder(Mutex::new(default_source_builder)),
198185
mode: AssetMode::Processed,
199186
use_asset_processor_override: Some(true),
200187
watch_for_changes_override: Some(true),
@@ -248,19 +235,25 @@ fn create_app_with_asset_processor(extra_sources: &[String]) -> AppWithProcessor
248235
.set_log_factory(Box::new(FakeTransactionLogFactory))
249236
.unwrap();
250237

251-
// Now that we've built the app, finish all the processing dirs.
238+
// Now that we've built the app, finish the default dir, and return it.
252239

253240
AppWithProcessor {
254241
app,
255242
source_gate,
256243
default_source_dirs: default_source_dirs.finish(),
257-
extra_sources_dirs: extra_sources_dirs
258-
.into_iter()
259-
.map(|(name, dirs)| (name, dirs.finish()))
260-
.collect(),
261244
}
262245
}
263246

247+
fn register_new_source(
248+
app: &mut App,
249+
name: impl Into<CowArc<'static, str>>,
250+
source_gate: Arc<RwLock<()>>,
251+
) -> ProcessingDirs {
252+
let (source, processing_dirs) = create_source(source_gate);
253+
app.register_asset_source(name.into(), source);
254+
processing_dirs.finish()
255+
}
256+
264257
fn run_app_until_finished_processing(app: &mut App, guard: RwLockWriteGuard<'_, ()>) {
265258
let processor = app.world().resource::<AssetProcessor>().clone();
266259
// We can't just wait for the processor state to be finished since we could have already
@@ -373,8 +366,7 @@ fn no_meta_or_default_processor_copies_asset() {
373366
processed: processed_dir,
374367
..
375368
},
376-
..
377-
} = create_app_with_asset_processor(&[]);
369+
} = create_app_with_asset_processor();
378370

379371
let guard = source_gate.write_blocking();
380372

@@ -406,8 +398,7 @@ fn asset_processor_transforms_asset_default_processor() {
406398
processed: processed_dir,
407399
..
408400
},
409-
..
410-
} = create_app_with_asset_processor(&[]);
401+
} = create_app_with_asset_processor();
411402

412403
type CoolTextProcessor = LoadTransformAndSave<
413404
CoolTextLoader,
@@ -460,8 +451,7 @@ fn asset_processor_transforms_asset_with_meta() {
460451
processed: processed_dir,
461452
..
462453
},
463-
..
464-
} = create_app_with_asset_processor(&[]);
454+
} = create_app_with_asset_processor();
465455

466456
type CoolTextProcessor = LoadTransformAndSave<
467457
CoolTextLoader,
@@ -657,8 +647,7 @@ fn asset_processor_loading_can_read_processed_assets() {
657647
processed: processed_dir,
658648
..
659649
},
660-
..
661-
} = create_app_with_asset_processor(&[]);
650+
} = create_app_with_asset_processor();
662651

663652
// This processor loads a gltf file, converts it to BSN and then saves out the BSN.
664653
type GltfProcessor = LoadTransformAndSave<FakeGltfLoader, GltfToBsn, FakeBsnSaver>;
@@ -731,8 +720,7 @@ fn asset_processor_loading_can_read_source_assets() {
731720
processed: processed_dir,
732721
..
733722
},
734-
..
735-
} = create_app_with_asset_processor(&[]);
723+
} = create_app_with_asset_processor();
736724

737725
#[derive(Serialize, Deserialize)]
738726
struct FakeGltfxData {
@@ -927,18 +915,18 @@ fn asset_processor_processes_all_sources() {
927915
processed: default_processed_dir,
928916
source_event_sender: default_source_events,
929917
},
930-
extra_sources_dirs,
931-
} = create_app_with_asset_processor(&["custom_1".into(), "custom_2".into()]);
918+
} = create_app_with_asset_processor();
919+
932920
let ProcessingDirs {
933921
source: custom_1_source_dir,
934922
processed: custom_1_processed_dir,
935923
source_event_sender: custom_1_source_events,
936-
} = extra_sources_dirs["custom_1"].clone();
924+
} = register_new_source(&mut app, "custom_1", source_gate.clone());
937925
let ProcessingDirs {
938926
source: custom_2_source_dir,
939927
processed: custom_2_processed_dir,
940928
source_event_sender: custom_2_source_events,
941-
} = extra_sources_dirs["custom_2"].clone();
929+
} = register_new_source(&mut app, "custom_2", source_gate.clone());
942930

943931
type AddTextProcessor = LoadTransformAndSave<
944932
CoolTextLoader,
@@ -1043,13 +1031,12 @@ fn nested_loads_of_processed_asset_reprocesses_on_reload() {
10431031
processed: default_processed_dir,
10441032
source_event_sender: default_source_events,
10451033
},
1046-
extra_sources_dirs,
1047-
} = create_app_with_asset_processor(&["custom".into()]);
1034+
} = create_app_with_asset_processor();
10481035
let ProcessingDirs {
10491036
source: custom_source_dir,
10501037
processed: custom_processed_dir,
10511038
source_event_sender: custom_source_events,
1052-
} = extra_sources_dirs["custom"].clone();
1039+
} = register_new_source(&mut app, "custom", source_gate.clone());
10531040

10541041
#[derive(Serialize, Deserialize)]
10551042
enum NesterSerialized {
@@ -1261,8 +1248,7 @@ fn clears_invalid_data_from_processed_dir() {
12611248
processed: default_processed_dir,
12621249
..
12631250
},
1264-
..
1265-
} = create_app_with_asset_processor(&[]);
1251+
} = create_app_with_asset_processor();
12661252

12671253
type CoolTextProcessor = LoadTransformAndSave<
12681254
CoolTextLoader,
@@ -1367,8 +1353,7 @@ fn only_reprocesses_wrong_hash_on_startup() {
13671353
mut app,
13681354
source_gate,
13691355
default_source_dirs,
1370-
..
1371-
} = create_app_with_asset_processor(&[]);
1356+
} = create_app_with_asset_processor();
13721357
default_source_dir = default_source_dirs.source;
13731358
default_processed_dir = default_source_dirs.processed;
13741359

@@ -1450,16 +1435,16 @@ fn only_reprocesses_wrong_hash_on_startup() {
14501435
root: default_processed_dir.clone(),
14511436
};
14521437

1453-
app.register_asset_source(
1454-
AssetSourceId::Default,
1455-
AssetSourceBuilder::new(move || Box::new(source_memory_reader.clone()))
1456-
.with_processed_reader(move || Box::new(processed_memory_reader.clone()))
1457-
.with_processed_writer(move |_| Some(Box::new(processed_memory_writer.clone()))),
1458-
);
1459-
14601438
app.add_plugins((
14611439
TaskPoolPlugin::default(),
14621440
AssetPlugin {
1441+
default_source: DefaultAssetSource::FromBuilder(Mutex::new(
1442+
AssetSourceBuilder::new(move || Box::new(source_memory_reader.clone()))
1443+
.with_processed_reader(move || Box::new(processed_memory_reader.clone()))
1444+
.with_processed_writer(move |_| {
1445+
Some(Box::new(processed_memory_writer.clone()))
1446+
}),
1447+
)),
14631448
mode: AssetMode::Processed,
14641449
use_asset_processor_override: Some(true),
14651450
..Default::default()

0 commit comments

Comments
 (0)