Skip to content

Commit 46f3dc1

Browse files
committed
Add some checks to verify the behavior of some error cases for invalid processors.
1 parent 266a0dc commit 46f3dc1

File tree

1 file changed

+267
-1
lines changed

1 file changed

+267
-1
lines changed

crates/bevy_asset/src/processor/tests.rs

Lines changed: 267 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ use crate::{
3232
meta::AssetMeta,
3333
processor::{
3434
AssetProcessor, LoadTransformAndSave, LogEntry, Process, ProcessContext, ProcessError,
35-
ProcessorState, ProcessorTransactionLog, ProcessorTransactionLogFactory, WriterContext,
35+
ProcessStatus, ProcessorState, ProcessorTransactionLog, ProcessorTransactionLogFactory,
36+
WriterContext,
3637
},
3738
saver::AssetSaver,
3839
tests::{run_app_until, CoolText, CoolTextLoader, CoolTextRon, SubText},
@@ -1939,3 +1940,268 @@ fn asset_processor_can_write_multiple_files() {
19391940
)"#
19401941
);
19411942
}
1943+
1944+
#[test]
1945+
fn error_on_no_writer() {
1946+
let AppWithProcessor {
1947+
mut app,
1948+
source_gate,
1949+
default_source_dirs: ProcessingDirs {
1950+
source: source_dir, ..
1951+
},
1952+
..
1953+
} = create_app_with_asset_processor(&[]);
1954+
1955+
struct NoWriterProcess;
1956+
1957+
impl Process for NoWriterProcess {
1958+
type Settings = ();
1959+
1960+
async fn process(
1961+
&self,
1962+
_: &mut ProcessContext<'_>,
1963+
_: AssetMeta<(), Self>,
1964+
_: WriterContext<'_>,
1965+
) -> Result<(), ProcessError> {
1966+
// Don't start a writer!
1967+
Ok(())
1968+
}
1969+
}
1970+
1971+
app.register_asset_processor(NoWriterProcess)
1972+
.set_default_asset_processor::<NoWriterProcess>("txt");
1973+
1974+
let guard = source_gate.write_blocking();
1975+
source_dir.insert_asset_text(Path::new("whatever.txt"), "");
1976+
1977+
run_app_until_finished_processing(&mut app, guard);
1978+
1979+
let process_status = bevy_tasks::block_on(
1980+
app.world()
1981+
.resource::<AssetProcessor>()
1982+
.data()
1983+
.wait_until_processed("whatever.txt".into()),
1984+
);
1985+
// The process failed due to not having a writer.
1986+
assert_eq!(process_status, ProcessStatus::Failed);
1987+
}
1988+
1989+
#[test]
1990+
fn error_on_unfinished_writer() {
1991+
let AppWithProcessor {
1992+
mut app,
1993+
source_gate,
1994+
default_source_dirs: ProcessingDirs {
1995+
source: source_dir, ..
1996+
},
1997+
..
1998+
} = create_app_with_asset_processor(&[]);
1999+
2000+
struct UnfinishedWriterProcess;
2001+
2002+
impl Process for UnfinishedWriterProcess {
2003+
type Settings = ();
2004+
2005+
async fn process(
2006+
&self,
2007+
_: &mut ProcessContext<'_>,
2008+
_: AssetMeta<(), Self>,
2009+
writer_context: WriterContext<'_>,
2010+
) -> Result<(), ProcessError> {
2011+
let _writer = writer_context.write_single().await?;
2012+
// Don't call finish on the writer!
2013+
Ok(())
2014+
}
2015+
}
2016+
2017+
app.register_asset_processor(UnfinishedWriterProcess)
2018+
.set_default_asset_processor::<UnfinishedWriterProcess>("txt");
2019+
2020+
let guard = source_gate.write_blocking();
2021+
source_dir.insert_asset_text(Path::new("whatever.txt"), "");
2022+
2023+
run_app_until_finished_processing(&mut app, guard);
2024+
2025+
let process_status = bevy_tasks::block_on(
2026+
app.world()
2027+
.resource::<AssetProcessor>()
2028+
.data()
2029+
.wait_until_processed("whatever.txt".into()),
2030+
);
2031+
// The process failed due to having a writer that we didn't await finish on.
2032+
assert_eq!(process_status, ProcessStatus::Failed);
2033+
}
2034+
2035+
#[test]
2036+
fn error_on_single_writer_after_multiple_writer() {
2037+
let AppWithProcessor {
2038+
mut app,
2039+
source_gate,
2040+
default_source_dirs: ProcessingDirs {
2041+
source: source_dir, ..
2042+
},
2043+
..
2044+
} = create_app_with_asset_processor(&[]);
2045+
2046+
struct SingleAfterMultipleWriterProcess;
2047+
2048+
impl Process for SingleAfterMultipleWriterProcess {
2049+
type Settings = ();
2050+
2051+
async fn process(
2052+
&self,
2053+
_: &mut ProcessContext<'_>,
2054+
_: AssetMeta<(), Self>,
2055+
writer_context: WriterContext<'_>,
2056+
) -> Result<(), ProcessError> {
2057+
// Properly write a "multiple".
2058+
let writer = writer_context
2059+
.write_multiple(Path::new("multi.txt"))
2060+
.await?;
2061+
writer.finish::<CoolTextLoader>(()).await?;
2062+
2063+
// Now trying writing "single", which conflicts!
2064+
let writer = writer_context.write_single().await?;
2065+
writer.finish::<CoolTextLoader>(()).await?;
2066+
2067+
Ok(())
2068+
}
2069+
}
2070+
2071+
app.register_asset_processor(SingleAfterMultipleWriterProcess)
2072+
.set_default_asset_processor::<SingleAfterMultipleWriterProcess>("txt");
2073+
2074+
let guard = source_gate.write_blocking();
2075+
source_dir.insert_asset_text(Path::new("whatever.txt"), "");
2076+
2077+
run_app_until_finished_processing(&mut app, guard);
2078+
2079+
let process_status = bevy_tasks::block_on(
2080+
app.world()
2081+
.resource::<AssetProcessor>()
2082+
.data()
2083+
.wait_until_processed("whatever.txt".into()),
2084+
);
2085+
// The process failed due to having a single writer after a multiple writer.
2086+
assert_eq!(process_status, ProcessStatus::Failed);
2087+
}
2088+
2089+
#[test]
2090+
fn processor_can_parallelize_multiple_writes() {
2091+
let AppWithProcessor {
2092+
mut app,
2093+
source_gate,
2094+
default_source_dirs:
2095+
ProcessingDirs {
2096+
source: source_dir,
2097+
processed: processed_dir,
2098+
..
2099+
},
2100+
..
2101+
} = create_app_with_asset_processor(&[]);
2102+
2103+
struct ParallelizedWriterProcess;
2104+
2105+
impl Process for ParallelizedWriterProcess {
2106+
type Settings = ();
2107+
2108+
async fn process(
2109+
&self,
2110+
_: &mut ProcessContext<'_>,
2111+
_: AssetMeta<(), Self>,
2112+
writer_context: WriterContext<'_>,
2113+
) -> Result<(), ProcessError> {
2114+
let mut writer_1 = writer_context.write_multiple(Path::new("a.txt")).await?;
2115+
let mut writer_2 = writer_context.write_multiple(Path::new("b.txt")).await?;
2116+
2117+
// Note: this call is blocking, so it's undesirable in production code using
2118+
// single-threaded mode (e.g., platforms like Wasm). For this test though, it's not a
2119+
// big deal.
2120+
bevy_tasks::IoTaskPool::get().scope(|scope| {
2121+
scope.spawn(async {
2122+
writer_1.write_all(b"abc123").await.unwrap();
2123+
writer_1.finish::<CoolTextLoader>(()).await.unwrap();
2124+
});
2125+
scope.spawn(async {
2126+
writer_2.write_all(b"def456").await.unwrap();
2127+
writer_2.finish::<CoolTextLoader>(()).await.unwrap();
2128+
});
2129+
});
2130+
2131+
Ok(())
2132+
}
2133+
}
2134+
2135+
app.register_asset_processor(ParallelizedWriterProcess)
2136+
.set_default_asset_processor::<ParallelizedWriterProcess>("txt");
2137+
2138+
let guard = source_gate.write_blocking();
2139+
source_dir.insert_asset_text(Path::new("whatever.txt"), "");
2140+
2141+
run_app_until_finished_processing(&mut app, guard);
2142+
2143+
assert_eq!(
2144+
&read_asset_as_string(&processed_dir, Path::new("whatever.txt/a.txt")),
2145+
"abc123"
2146+
);
2147+
assert_eq!(
2148+
&read_asset_as_string(&processed_dir, Path::new("whatever.txt/b.txt")),
2149+
"def456"
2150+
);
2151+
}
2152+
2153+
#[test]
2154+
fn error_on_two_multiple_writes_for_same_path() {
2155+
let AppWithProcessor {
2156+
mut app,
2157+
source_gate,
2158+
default_source_dirs: ProcessingDirs {
2159+
source: source_dir, ..
2160+
},
2161+
..
2162+
} = create_app_with_asset_processor(&[]);
2163+
2164+
struct TwoMultipleWritesForSamePathProcess;
2165+
2166+
impl Process for TwoMultipleWritesForSamePathProcess {
2167+
type Settings = ();
2168+
2169+
async fn process(
2170+
&self,
2171+
_: &mut ProcessContext<'_>,
2172+
_: AssetMeta<(), Self>,
2173+
writer_context: WriterContext<'_>,
2174+
) -> Result<(), ProcessError> {
2175+
// Properly write a "multiple".
2176+
let writer = writer_context
2177+
.write_multiple(Path::new("multi.txt"))
2178+
.await?;
2179+
writer.finish::<CoolTextLoader>(()).await?;
2180+
2181+
// Properly write to the same "multiple".
2182+
let writer = writer_context
2183+
.write_multiple(Path::new("multi.txt"))
2184+
.await?;
2185+
writer.finish::<CoolTextLoader>(()).await?;
2186+
2187+
Ok(())
2188+
}
2189+
}
2190+
2191+
app.register_asset_processor(TwoMultipleWritesForSamePathProcess)
2192+
.set_default_asset_processor::<TwoMultipleWritesForSamePathProcess>("txt");
2193+
2194+
let guard = source_gate.write_blocking();
2195+
source_dir.insert_asset_text(Path::new("whatever.txt"), "");
2196+
2197+
run_app_until_finished_processing(&mut app, guard);
2198+
2199+
let process_status = bevy_tasks::block_on(
2200+
app.world()
2201+
.resource::<AssetProcessor>()
2202+
.data()
2203+
.wait_until_processed("whatever.txt".into()),
2204+
);
2205+
// The process failed due to writing "multiple" to the same path twice.
2206+
assert_eq!(process_status, ProcessStatus::Failed);
2207+
}

0 commit comments

Comments
 (0)