tests: Move all wgpu code out of test framework, make it abstract over any/no renderer, and make wgpu option if imgtests isn't enabled

This commit is contained in:
Nathan Adams 2023-11-09 15:36:46 +01:00
parent c36f4cfe95
commit bce0608e1f
12 changed files with 265 additions and 160 deletions

4
Cargo.lock generated
View File

@ -4271,7 +4271,6 @@ dependencies = [
"ruffle_core",
"ruffle_input_format",
"ruffle_render",
"ruffle_render_wgpu",
"ruffle_socket_format",
"ruffle_video_software",
"serde",
@ -4922,8 +4921,11 @@ name = "tests"
version = "0.1.0"
dependencies = [
"anyhow",
"futures",
"image",
"libtest-mimic",
"ruffle_core",
"ruffle_render_wgpu",
"ruffle_test_framework",
"walkdir",
]

View File

@ -2270,6 +2270,13 @@ impl PlayerBuilder {
self
}
/// Sets the rendering backend of the player.
#[inline]
pub fn with_boxed_renderer(mut self, renderer: Box<dyn RenderBackend>) -> Self {
self.renderer = Some(renderer);
self
}
/// Sets the storage backend of the player.
#[inline]
pub fn with_storage(mut self, storage: impl 'static + StorageBackend) -> Self {

View File

@ -11,16 +11,21 @@ version.workspace = true
# Enable running image comparison tests. This is off by default,
# since the images we compare against are generated on CI, and may
# not match your local machine's Vulkan version / image output.
imgtests = ["ruffle_test_framework/imgtests"]
imgtests = ["ruffle_test_framework/ruffle_video_software", "ruffle_render_wgpu"]
jpegxr = ["ruffle_test_framework/jpegxr"]
lzma = ["ruffle_test_framework/lzma"]
[dependencies]
ruffle_render_wgpu = { path = "../render/wgpu", optional = true }
[dev-dependencies]
ruffle_core = { path = "../core", features = ["deterministic", "timeline_debug", "avm_debug", "audio", "mp3", "default_font"] }
ruffle_test_framework = { path = "framework" }
libtest-mimic = "0.6.1"
walkdir = "2.4.0"
anyhow = "1.0.75"
image = { version = "0.24.7", default-features = false, features = ["png"] }
futures = "0.3.29"
[[test]]
name = "tests"

View File

@ -10,12 +10,11 @@ version.workspace = true
[dependencies]
futures = "0.3.29"
ruffle_core = { path = "../../core", features = ["deterministic", "timeline_debug", "avm_debug", "audio", "mp3", "default_font"] }
ruffle_render_wgpu = { path = "../../render/wgpu" }
ruffle_render = { path = "../../render" }
ruffle_input_format = { path = "../input-format" }
ruffle_socket_format = { path = "../socket-format" }
ruffle_video_software = { path = "../../video/software", optional = true }
image = { version = "0.24.7", default-features = false, features = ["png"] }
image = { version = "0.24.7", default-features = false, features = ["png"] }
regex = "1.10.2"
url = "2.4.1"
chrono = "0.4.31"
@ -32,6 +31,5 @@ anyhow = "1.0.75"
async-channel = "1.9.0"
[features]
imgtests = ["ruffle_video_software"]
jpegxr = ["ruffle_core/jpegxr"]
lzma = ["ruffle_core/lzma"]

View File

@ -1,43 +1,33 @@
use ruffle_render_wgpu::backend::request_adapter_and_device;
use ruffle_render_wgpu::descriptors::Descriptors;
use ruffle_render_wgpu::wgpu;
use std::sync::{Arc, OnceLock};
use crate::options::RenderOptions;
/*
It can be expensive to construct WGPU, much less Descriptors, so we put it off as long as we can
and share it across tests in the same process.
pub use ruffle_render::backend::RenderBackend;
Remember:
`cargo test` will run all tests in the same process.
`cargo nextest run` will create a different process per test.
pub trait Environment {
/// Checks if this environment supports rendering the given test.
///
/// This isn't a guarantee that it _will_ construct a renderer,
/// but rather a check that it theoretically _can_.
///
/// This should be a cheap test to filter out test viability early,
/// without creating any expensive rendering overhead.
fn is_render_supported(&self, _requirements: &RenderOptions) -> bool {
false
}
For `cargo test` it's relatively okay if we spend the time to construct descriptors once,
but for `cargo nextest run` it's a big cost per test if it's not going to use it.
*/
fn create_wgpu_device() -> Option<(wgpu::Instance, wgpu::Adapter, wgpu::Device, wgpu::Queue)> {
let instance = wgpu::Instance::new(Default::default());
futures::executor::block_on(request_adapter_and_device(
wgpu::Backends::all(),
&instance,
None,
Default::default(),
None,
))
.ok()
.map(|(adapter, device, queue)| (instance, adapter, device, queue))
}
fn build_wgpu_descriptors() -> Option<Arc<Descriptors>> {
if let Some((instance, adapter, device, queue)) = create_wgpu_device() {
Some(Arc::new(Descriptors::new(instance, adapter, device, queue)))
} else {
/// Creates a render backend for the given test.
///
/// If [Self::is_render_supported] returned false, this won't be attempted.
fn create_renderer(&self, _width: u32, _height: u32) -> Option<Box<dyn RenderBackend>> {
None
}
}
pub fn wgpu_descriptors() -> Option<&'static Arc<Descriptors>> {
// TODO: Use `std::sync::LazyLock` once it's stabilized?
static WGPU: OnceLock<Option<Arc<Descriptors>>> = OnceLock::new();
WGPU.get_or_init(build_wgpu_descriptors).as_ref()
/// Gets the name of this environment, for use in test reporting.
///
/// This name may be used in file paths, so it should contain appropriate characters for such.
fn name(&self) -> String;
/// Capture the stage rendered out by the given render backend.
///
/// The provided backend will have previously been created by [Environment::create_renderer].
fn capture_renderer(&self, renderer: &mut Box<dyn RenderBackend>) -> image::RgbaImage;
}

View File

@ -1,5 +1,5 @@
use crate::backends::TestAudioBackend;
use crate::environment::wgpu_descriptors;
use crate::environment::Environment;
use crate::image_trigger::ImageTrigger;
use anyhow::{anyhow, Result};
use approx::assert_relative_eq;
@ -7,7 +7,6 @@ use regex::Regex;
use ruffle_core::tag_utils::SwfMovie;
use ruffle_core::{PlayerBuilder, ViewportDimensions};
use ruffle_render::quality::StageQuality;
use ruffle_render_wgpu::wgpu;
use serde::Deserialize;
use std::collections::{HashMap, HashSet};
use std::fs;
@ -141,6 +140,7 @@ impl PlayerOptions {
&self,
mut player_builder: PlayerBuilder,
movie: &SwfMovie,
environment: &impl Environment,
) -> Result<PlayerBuilder> {
if let Some(max_execution_duration) = self.max_execution_duration {
player_builder = player_builder.with_max_execution_duration(max_execution_duration);
@ -161,27 +161,16 @@ impl PlayerOptions {
};
if let Some(render_options) = &self.with_renderer {
use ruffle_render_wgpu::backend::WgpuRenderBackend;
use ruffle_render_wgpu::target::TextureTarget;
player_builder = player_builder.with_quality(match render_options.sample_count {
16 => StageQuality::High16x16,
8 => StageQuality::High8x8,
4 => StageQuality::High,
2 => StageQuality::Medium,
_ => StageQuality::Low,
});
if let Some(descriptors) = wgpu_descriptors() {
if render_options.is_supported(&descriptors.adapter) {
let target = TextureTarget::new(&descriptors.device, (width, height))
.map_err(|e| anyhow!(e.to_string()))?;
player_builder = player_builder
.with_quality(match render_options.sample_count {
16 => StageQuality::High16x16,
8 => StageQuality::High8x8,
4 => StageQuality::High,
2 => StageQuality::Medium,
_ => StageQuality::Low,
})
.with_renderer(
WgpuRenderBackend::new(descriptors.clone(), target)
.map_err(|e| anyhow!(e.to_string()))?,
);
}
if let Some(renderer) = environment.create_renderer(width, height) {
player_builder = player_builder.with_boxed_renderer(renderer);
}
}
@ -189,7 +178,7 @@ impl PlayerOptions {
player_builder = player_builder.with_audio(TestAudioBackend::default());
}
#[cfg(feature = "imgtests")]
#[cfg(feature = "ruffle_video_software")]
if self.with_video {
use ruffle_video_software::backend::SoftwareVideoBackend;
player_builder = player_builder.with_video(SoftwareVideoBackend::new())
@ -198,18 +187,12 @@ impl PlayerOptions {
Ok(player_builder)
}
pub fn can_run(&self, check_renderer: bool) -> bool {
pub fn can_run(&self, check_renderer: bool, environment: &impl Environment) -> bool {
if let Some(render) = &self.with_renderer {
// If we don't actually want to check the renderer (ie we're just listing potential tests),
// don't spend the cost to create it
if check_renderer && !render.optional {
if let Some(descriptors) = wgpu_descriptors() {
if !render.is_supported(&descriptors.adapter) {
return false;
}
} else {
return false;
}
if check_renderer && !render.optional && !environment.is_render_supported(render) {
return false;
}
}
true
@ -224,31 +207,27 @@ pub struct ImageComparison {
pub trigger: ImageTrigger,
}
#[cfg(feature = "imgtests")]
fn calc_difference(lhs: u8, rhs: u8) -> u8 {
(lhs as i16 - rhs as i16).unsigned_abs() as u8
}
impl ImageComparison {
#[cfg(feature = "imgtests")]
pub fn test(
&self,
name: &str,
actual_image: image::RgbaImage,
expected_image: image::RgbaImage,
test_path: &Path,
adapter_info: wgpu::AdapterInfo,
environment_name: String,
known_failure: bool,
) -> Result<()> {
use anyhow::Context;
let suffix = format!("{}-{:?}", std::env::consts::OS, adapter_info.backend);
let save_actual_image = || {
if !known_failure {
// If we're expecting failure, spamming files isn't productive.
actual_image
.save(test_path.join(format!("{name}.actual-{suffix}.png")))
.save(test_path.join(format!("{name}.actual-{environment_name}.png")))
.context("Couldn't save actual image")
} else {
Ok(())
@ -323,7 +302,7 @@ impl ImageComparison {
difference_color,
)
.context("Couldn't create color difference image")?
.save(test_path.join(format!("{name}.difference-color-{suffix}.png")))
.save(test_path.join(format!("{name}.difference-color-{environment_name}.png")))
.context("Couldn't save color difference image")?;
}
@ -343,7 +322,7 @@ impl ImageComparison {
difference_alpha,
)
.context("Couldn't create alpha difference image")?
.save(test_path.join(format!("{name}.difference-alpha-{suffix}.png")))
.save(test_path.join(format!("{name}.difference-alpha-{environment_name}.png")))
.context("Couldn't save alpha difference image")?;
}
}
@ -367,8 +346,8 @@ impl ImageComparison {
#[serde(default, deny_unknown_fields)]
pub struct RenderOptions {
optional: bool,
sample_count: u32,
exclude_warp: bool,
pub sample_count: u32,
pub exclude_warp: bool,
}
impl Default for RenderOptions {
@ -380,14 +359,3 @@ impl Default for RenderOptions {
}
}
}
impl RenderOptions {
pub fn is_supported(&self, adapter: &wgpu::Adapter) -> bool {
let info = adapter.get_info();
// 5140 & 140 is WARP, https://learn.microsoft.com/en-us/windows/win32/direct3ddxgi/d3d10-graphics-programming-guide-dxgi#new-info-about-enumerating-adapters-for-windows-8
if self.exclude_warp && cfg!(windows) && info.vendor == 5140 && info.device == 140 {
return false;
}
true
}
}

View File

@ -1,4 +1,5 @@
use crate::backends::{TestLogBackend, TestNavigatorBackend};
use crate::environment::Environment;
use crate::fs_commands::{FsCommand, TestFsCommandProvider};
use crate::image_trigger::ImageTrigger;
use crate::options::ImageComparison;
@ -15,7 +16,7 @@ use ruffle_input_format::{
AutomatedEvent, InputInjector, MouseButton as InputMouseButton,
TextControlCode as InputTextControlCode,
};
use ruffle_render_wgpu::descriptors::Descriptors;
use ruffle_render::backend::null::NullRenderer;
use ruffle_socket_format::SocketEvent;
use std::path::Path;
use std::sync::{Arc, Mutex};
@ -29,6 +30,7 @@ pub fn run_swf(
socket_events: Option<Vec<SocketEvent>>,
before_start: impl FnOnce(Arc<Mutex<Player>>) -> Result<()>,
before_end: impl FnOnce(Arc<Mutex<Player>>) -> Result<()>,
environment: &impl Environment,
) -> Result<String> {
let base_path = Path::new(&test.output_path).parent().unwrap();
let mut executor = NullExecutor::new();
@ -65,18 +67,20 @@ pub fn run_swf(
let player = test
.options
.player_options
.setup(builder, &movie)?
.setup(builder, &movie, environment)?
.with_movie(movie)
.with_autoplay(true) //.tick() requires playback
.build();
let mut images = test.options.image_comparisons.clone();
// If we set anything but a null renderer, then the Environment must have created a valid renderer.
let has_renderer = player
.lock()
.unwrap()
.renderer()
.downcast_ref::<NullRenderer>()
.is_none();
let wgpu_descriptors = if cfg!(feature = "imgtests") && !images.is_empty() {
crate::environment::wgpu_descriptors()
} else {
None
};
let mut images = test.options.image_comparisons.clone();
before_start(player.clone())?;
@ -142,10 +146,11 @@ pub fn run_swf(
capture_and_compare_image(
base_path,
&player,
wgpu_descriptors,
&name,
image_comparison,
test.options.known_failure,
environment,
has_renderer,
)?;
} else {
return Err(anyhow!("Encountered fscommand to capture and compare image '{name}', but no [image_comparison] was set up for this."));
@ -214,10 +219,11 @@ pub fn run_swf(
capture_and_compare_image(
base_path,
&player,
wgpu_descriptors,
&name,
image_comparison,
test.options.known_failure,
environment,
has_renderer,
)?;
}
}
@ -234,10 +240,11 @@ pub fn run_swf(
capture_and_compare_image(
base_path,
&player,
wgpu_descriptors,
&name,
image_comparison,
test.options.known_failure,
environment,
has_renderer,
)?;
}
@ -260,48 +267,22 @@ pub fn run_swf(
Ok(normalized_trace)
}
#[cfg(not(feature = "imgtests"))]
fn capture_and_compare_image(
_base_path: &Path,
_player: &Arc<Mutex<Player>>,
_wgpu_descriptors: Option<&Arc<Descriptors>>,
_name: &str,
_image_comparison: ImageComparison,
known_failure: bool,
) -> Result<()> {
if known_failure {
// It's possible that the trace output matched but the image might not.
// If we aren't checking the image, pretend the match failed (which makes it actually pass, since it's expecting failure).
Err(anyhow!(
"Not checking images, pretending this failed since we don't know if it worked."
))
} else {
Ok(())
}
}
#[cfg(feature = "imgtests")]
fn capture_and_compare_image(
base_path: &Path,
player: &Arc<Mutex<Player>>,
wgpu_descriptors: Option<&Arc<Descriptors>>,
name: &String,
image_comparison: ImageComparison,
known_failure: bool,
environment: &impl Environment,
has_renderer: bool,
) -> Result<()> {
use anyhow::Context;
use ruffle_render_wgpu::backend::WgpuRenderBackend;
use ruffle_render_wgpu::target::TextureTarget;
if let Some(wgpu_descriptors) = wgpu_descriptors {
if has_renderer {
let mut player_lock = player.lock().unwrap();
player_lock.render();
let renderer = player_lock
.renderer_mut()
.downcast_mut::<WgpuRenderBackend<TextureTarget>>()
.unwrap();
let actual_image = renderer.capture_frame().expect("Failed to capture image");
let actual_image = environment.capture_renderer(player_lock.renderer_mut());
let expected_image_path = base_path.join(format!("{name}.expected.png"));
if expected_image_path.is_file() {
@ -314,7 +295,7 @@ fn capture_and_compare_image(
actual_image,
expected_image,
base_path,
wgpu_descriptors.adapter.get_info(),
environment.name(),
known_failure,
)?;
} else if !known_failure {

View File

@ -1,3 +1,4 @@
use crate::environment::Environment;
use crate::options::TestOptions;
use crate::runner::run_swf;
use crate::set_logger;
@ -49,6 +50,7 @@ impl Test {
&self,
before_start: impl FnOnce(Arc<Mutex<Player>>) -> Result<()>,
before_end: impl FnOnce(Arc<Mutex<Player>>) -> Result<()>,
environment: &impl Environment,
) -> std::result::Result<(), libtest_mimic::Failed> {
set_logger();
let injector = if self.input_path.is_file() {
@ -61,17 +63,27 @@ impl Test {
} else {
None
};
let output = run_swf(self, injector, socket_events, before_start, before_end)?;
let output = run_swf(
self,
injector,
socket_events,
before_start,
before_end,
environment,
)?;
self.compare_output(&output)?;
Ok(())
}
pub fn should_run(&self, check_renderer: bool) -> bool {
pub fn should_run(&self, check_renderer: bool, environment: &impl Environment) -> bool {
if self.options.ignore {
return false;
}
self.options.required_features.can_run()
&& self.options.player_options.can_run(check_renderer)
&& self
.options
.player_options
.can_run(check_renderer, environment)
}
pub fn compare_output(&self, actual_output: &str) -> Result<()> {

123
tests/tests/environment.rs Normal file
View File

@ -0,0 +1,123 @@
use image::RgbaImage;
use ruffle_test_framework::environment::{Environment, RenderBackend};
#[cfg(feature = "imgtests")]
use ruffle_test_framework::options::RenderOptions;
#[cfg(feature = "imgtests")]
use ruffle_render_wgpu::{
backend::{request_adapter_and_device, WgpuRenderBackend},
descriptors::Descriptors,
target::TextureTarget,
wgpu,
};
#[cfg(feature = "imgtests")]
use {std::sync::Arc, std::sync::OnceLock};
pub struct NativeEnvironment;
impl NativeEnvironment {
#[cfg(feature = "imgtests")]
fn descriptors(&self) -> Option<&Arc<Descriptors>> {
WGPU.get_or_init(build_wgpu_descriptors).as_ref()
}
}
impl Environment for NativeEnvironment {
#[cfg(feature = "imgtests")]
fn is_render_supported(&self, requirements: &RenderOptions) -> bool {
if let Some(descriptors) = self.descriptors() {
let adapter_info = descriptors.adapter.get_info();
let is_warp =
cfg!(windows) && adapter_info.vendor == 5140 && adapter_info.device == 140;
!requirements.exclude_warp || !is_warp
} else {
false
}
}
#[cfg(feature = "imgtests")]
fn create_renderer(&self, width: u32, height: u32) -> Option<Box<dyn RenderBackend>> {
if let Some(descriptors) = self.descriptors() {
let target = TextureTarget::new(&descriptors.device, (width, height)).expect(
"WGPU Texture Target creation must not fail, everything was checked ahead of time",
);
Some(Box::new(
WgpuRenderBackend::new(descriptors.clone(), target)
.expect("WGPU Render backend creation must not fail, everything was checked ahead of time"),
))
} else {
None
}
}
#[cfg(not(feature = "imgtests"))]
fn name(&self) -> String {
std::env::consts::OS.to_string()
}
#[cfg(feature = "imgtests")]
fn name(&self) -> String {
if let Some(descriptors) = self.descriptors() {
let adapter_info = descriptors.adapter.get_info();
format!("{}-{:?}", std::env::consts::OS, adapter_info.backend)
} else {
std::env::consts::OS.to_string()
}
}
#[cfg(not(feature = "imgtests"))]
fn capture_renderer(&self, _backend: &mut Box<dyn RenderBackend>) -> RgbaImage {
panic!("Cannot capture renderer as imgtests are not enabled")
}
#[cfg(feature = "imgtests")]
fn capture_renderer(&self, backend: &mut Box<dyn RenderBackend>) -> RgbaImage {
let renderer = backend
.downcast_mut::<WgpuRenderBackend<TextureTarget>>()
.unwrap();
renderer.capture_frame().expect("Failed to capture image")
}
}
#[cfg(feature = "imgtests")]
static WGPU: OnceLock<Option<Arc<Descriptors>>> = OnceLock::new();
/*
It can be expensive to construct WGPU, much less Descriptors, so we put it off as long as we can
and share it across tests in the same process.
Remember:
`cargo test` will run all tests in the same process.
`cargo nextest run` will create a different process per test.
For `cargo test` it's relatively okay if we spend the time to construct descriptors once,
but for `cargo nextest run` it's a big cost per test if it's not going to use it.
*/
#[cfg(feature = "imgtests")]
fn create_wgpu_device() -> Option<(wgpu::Instance, wgpu::Adapter, wgpu::Device, wgpu::Queue)> {
let instance = wgpu::Instance::new(Default::default());
futures::executor::block_on(request_adapter_and_device(
wgpu::Backends::all(),
&instance,
None,
Default::default(),
None,
))
.ok()
.map(|(adapter, device, queue)| (instance, adapter, device, queue))
}
#[cfg(feature = "imgtests")]
fn build_wgpu_descriptors() -> Option<Arc<Descriptors>> {
if let Some((instance, adapter, device, queue)) = create_wgpu_device() {
Some(Arc::new(Descriptors::new(instance, adapter, device, queue)))
} else {
None
}
}

View File

@ -1,12 +1,15 @@
use crate::external_interface::ExternalInterfaceTestProvider;
use ruffle_core::external::Value as ExternalValue;
use ruffle_test_framework::environment::Environment;
use ruffle_test_framework::options::TestOptions;
use ruffle_test_framework::set_logger;
use ruffle_test_framework::test::Test;
use std::collections::BTreeMap;
use std::path::Path;
pub fn external_interface_avm1() -> Result<(), libtest_mimic::Failed> {
pub fn external_interface_avm1(
environment: &impl Environment,
) -> Result<(), libtest_mimic::Failed> {
set_logger();
Test::from_options(
TestOptions {
@ -59,10 +62,13 @@ pub fn external_interface_avm1() -> Result<(), libtest_mimic::Failed> {
));
Ok(())
},
environment,
)
}
pub fn external_interface_avm2() -> Result<(), libtest_mimic::Failed> {
pub fn external_interface_avm2(
environment: &impl Environment,
) -> Result<(), libtest_mimic::Failed> {
set_logger();
Test::from_options(
TestOptions {
@ -106,5 +112,6 @@ pub fn external_interface_avm2() -> Result<(), libtest_mimic::Failed> {
));
Ok(())
},
environment,
)
}

View File

@ -2,6 +2,7 @@
//!
//! Trace output can be compared with correct output from the official Flash Player.
use crate::environment::NativeEnvironment;
use crate::external_interface::tests::{external_interface_avm1, external_interface_avm2};
use crate::shared_object::{shared_object_avm1, shared_object_avm2, shared_object_self_ref_avm1};
use anyhow::Context;
@ -11,6 +12,7 @@ use ruffle_test_framework::test::Test;
use std::panic::{catch_unwind, resume_unwind};
use std::path::Path;
mod environment;
mod external_interface;
mod shared_object;
@ -55,9 +57,9 @@ fn main() {
let test = Test::from_options_file(file.path(), name.clone())
.with_context(|| format!("Couldn't create test {name}"))
.unwrap();
let ignore = !test.should_run(!args.list);
let ignore = !test.should_run(!args.list, &NativeEnvironment);
let mut trial = Trial::test(test.name.to_string(), move || {
let unwind_result = catch_unwind(|| test.run(|_| Ok(()), |_| Ok(())));
let unwind_result = catch_unwind(|| test.run(|_| Ok(()), |_| Ok(()), &NativeEnvironment));
if test.options.known_failure {
match unwind_result {
Ok(Ok(())) => Err(
@ -83,20 +85,21 @@ fn main() {
.collect();
// Manual tests here, since #[test] doesn't work once we use our own test harness
tests.push(Trial::test("shared_object_avm1", shared_object_avm1));
tests.push(Trial::test(
"shared_object_self_ref_avm1",
shared_object_self_ref_avm1,
));
tests.push(Trial::test("shared_object_avm2", shared_object_avm2));
tests.push(Trial::test(
"external_interface_avm1",
external_interface_avm1,
));
tests.push(Trial::test(
"external_interface_avm2",
external_interface_avm2,
));
tests.push(Trial::test("shared_object_avm1", || {
shared_object_avm1(&NativeEnvironment)
}));
tests.push(Trial::test("shared_object_self_ref_avm1", || {
shared_object_self_ref_avm1(&NativeEnvironment)
}));
tests.push(Trial::test("shared_object_avm2", || {
shared_object_avm2(&NativeEnvironment)
}));
tests.push(Trial::test("external_interface_avm1", || {
external_interface_avm1(&NativeEnvironment)
}));
tests.push(Trial::test("external_interface_avm2", || {
external_interface_avm2(&NativeEnvironment)
}));
tests.sort_unstable_by(|a, b| a.name().cmp(b.name()));

View File

@ -1,10 +1,11 @@
use ruffle_core::backend::storage::{MemoryStorageBackend, StorageBackend};
use ruffle_test_framework::environment::Environment;
use ruffle_test_framework::options::TestOptions;
use ruffle_test_framework::set_logger;
use ruffle_test_framework::test::Test;
use std::path::Path;
pub fn shared_object_avm1() -> Result<(), libtest_mimic::Failed> {
pub fn shared_object_avm1(environment: &impl Environment) -> Result<(), libtest_mimic::Failed> {
set_logger();
// Test SharedObject persistence. Run an SWF that saves data
// to a shared object twice and verify that the data is saved.
@ -29,6 +30,7 @@ pub fn shared_object_avm1() -> Result<(), libtest_mimic::Failed> {
std::mem::swap(player.storage_mut(), &mut memory_storage_backend);
Ok(())
},
environment,
)?;
// Verify that the flash cookie matches the expected one
@ -58,12 +60,15 @@ pub fn shared_object_avm1() -> Result<(), libtest_mimic::Failed> {
Ok(())
},
|_| Ok(()),
environment,
)?;
Ok(())
}
pub fn shared_object_self_ref_avm1() -> Result<(), libtest_mimic::Failed> {
pub fn shared_object_self_ref_avm1(
environment: &impl Environment,
) -> Result<(), libtest_mimic::Failed> {
set_logger();
// Test SharedObject persistence. Run an SWF that saves data
// to a shared object twice and verify that the data is saved.
@ -88,6 +93,7 @@ pub fn shared_object_self_ref_avm1() -> Result<(), libtest_mimic::Failed> {
std::mem::swap(player.storage_mut(), &mut memory_storage_backend);
Ok(())
},
environment,
)?;
// Verify that the flash cookie matches the expected one
@ -117,12 +123,13 @@ pub fn shared_object_self_ref_avm1() -> Result<(), libtest_mimic::Failed> {
Ok(())
},
|_| Ok(()),
environment,
)?;
Ok(())
}
pub fn shared_object_avm2() -> Result<(), libtest_mimic::Failed> {
pub fn shared_object_avm2(environment: &impl Environment) -> Result<(), libtest_mimic::Failed> {
set_logger();
// Test SharedObject persistence. Run an SWF that saves data
// to a shared object twice and verify that the data is saved.
@ -147,6 +154,7 @@ pub fn shared_object_avm2() -> Result<(), libtest_mimic::Failed> {
std::mem::swap(player.storage_mut(), &mut memory_storage_backend);
Ok(())
},
environment,
)?;
// Verify that the flash cookie matches the expected one
@ -176,6 +184,7 @@ pub fn shared_object_avm2() -> Result<(), libtest_mimic::Failed> {
Ok(())
},
|_player| Ok(()),
environment,
)?;
Ok(())