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 Refactor #1382

Merged
merged 50 commits into from
Apr 16, 2020
Merged

Test Refactor #1382

merged 50 commits into from
Apr 16, 2020

Conversation

syrusakbary
Copy link
Member

@syrusakbary syrusakbary commented Apr 15, 2020

Description

This PR is the continuation of #1380.
It refactors our testing infrastructure based on various points:

  • There is no longer a "default compiler" on tests
  • Tests are automatically generated for: emscripten and wasi
  • It accelerates testing into multiple threads when possible (with the exception of the llvm backend)
  • It automatically detects the backends available in the host

Summary of changes:

  • Removed all extra logic for test creation in emscripten test generator
  • Removed all extra logic for test creation in the wasi test generator
  • Divided wasmer wast test in different files (under tests/custom/)
  • Refactored trap asserts using the wast format
  • Improved the build script by adding emscripten and wasi test generators (separated from build)
  • Improved WASI errors to be Rust error types (by deriving from thiserror::Error)
  • Fixed toolchain error creation
  • Removed leaking of testing logic from generators into build
  • Refactored import tests to be compatible with multiple backends
  • Improved wasmer binary to work even when no backends are set (useful for testing without any backend available).
  • Removed assumption that Cranelift will be the default in the wasmer binary
  • Migrated middleware

Review

  • Add a short description of the the change to the CHANGELOG.md file

@@ -56,15 +57,23 @@ impl std::fmt::Debug for WasiStateBuilder {
}

/// Error type returned when bad data is given to [`WasiStateBuilder`].
#[derive(Debug, PartialEq, Eq)]
#[derive(Error, Debug, PartialEq, Eq)]
Copy link
Member Author

Choose a reason for hiding this comment

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

Note, this is needed because anyhow (used in the wasi tests) needs to receive an Rust error, and it throw me a compiler error when trying to map our errors to anyhow.

So it's actually something that makes our API better as well!
I prefered to do it in one stand, rather than in a PR apart because otherwise I will forget.

build.rs Outdated Show resolved Hide resolved
Cargo.toml Show resolved Hide resolved
Copy link
Contributor

@nlewycky nlewycky left a comment

Choose a reason for hiding this comment

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

Unfinished review comments.

Cargo.toml Outdated Show resolved Hide resolved
Makefile Outdated Show resolved Hide resolved
build.rs Outdated Show resolved Hide resolved
build.rs Outdated Show resolved Hide resolved
lib/runtime/src/lib.rs Outdated Show resolved Hide resolved
tests/custom/multiple-traps.wast Outdated Show resolved Hide resolved
tests/generate-wasi-tests/src/set_up_toolchain.rs Outdated Show resolved Hide resolved
lib/wasi/Cargo.toml Outdated Show resolved Hide resolved
@@ -291,7 +298,7 @@ pub fn instantiate(wasm: &[u8], import_object: &ImportObject) -> error::Result<I
/// The output of this function can be controlled by the mutually
/// exclusive `default-backend-llvm`, `default-backend-singlepass`,
/// and `default-backend-cranelift` feature flags.
pub fn default_compiler() -> impl Compiler {
pub fn default_compiler() -> Box<dyn Compiler> {
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the reason this is now a dynamic trait object?

Copy link
Contributor

Choose a reason for hiding this comment

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

I thought it might be because the compiler can't be statically known anymore, but that doesn't seem to be the case

Copy link
Member Author

Choose a reason for hiding this comment

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

The main reason for this is because I wanted runtime to be compilable even when no backends where set (via the backend- feature).

However, this caused a compilation error in Rust, mentioning that it didn't know the size of Compiler (since for Rust this looked like an empty function).
I tried to resolve it by doing panic! at the end of the function body, but the compilation error still happened, so I changed into a Box` that Rust liked it.

Copy link
Member Author

Choose a reason for hiding this comment

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

Perhaps there are other ways of doing this, let me know if you have ideas @MarkMcCaskey!

Copy link
Contributor

Choose a reason for hiding this comment

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

From an efficiency perspective, this doesn't matter at all, but there are some usability concerns.

If users can interact with compilers outside of the Compiler trait, then impl Compiler is strictly better because it's more direct:

let compiler: LLVMCompiler = default_compiler();
compiler.llvm_compiler_specific_method();

Whereas with Box<dyn Compiler> the user has to do some kind of downcasting (I'm not sure how to do this without looking at docs, but I believe it's possible and will require an unwrap).

Also to avoid API breaking it might be worth it to make it work...

One way to do this is to add a Fail compiler which panics on every method... though that really raises the question, in what scenario will a user be compiling with no backends and be calling default_compiler? The only scenario I can think of right now is if the user is making a mistake: if that's the case, then perhaps we want to just remove the default_compiler function if no compiler backends are enabled 🤔

Cargo.toml Outdated Show resolved Hide resolved
build.rs Outdated Show resolved Hide resolved
build.rs Outdated Show resolved Hide resolved
build.rs Outdated Show resolved Hide resolved
@syrusakbary syrusakbary requested a review from losfair as a code owner April 16, 2020 01:42
Copy link
Contributor

@MarkMcCaskey MarkMcCaskey left a comment

Choose a reason for hiding this comment

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

Looks good to me! I want to spend some time trying to break the tests locally before approving -- I'll let you know if I find anything wrong with the tests!

@@ -351,6 +351,10 @@ pub mod error {
/// Idea for generic trait; consider rename; it will need to be moved somewhere else
pub trait CompiledModule {
fn new(bytes: impl AsRef<[u8]>) -> error::CompileResult<Module>;
fn new_with_compiler(
bytes: impl AsRef<[u8]>,
compiler: Box<dyn compiler::Compiler>,
Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't strictly have to take a Box we can use &dyn compiler::Compiler or AsRef<&dyn compiler::Compiler> or maybe Deref to be slightly more ergonmic.

Small bike-shed which we can do in a separate pass over our new public APIs before the next release instead of in this PR.

@@ -365,6 +369,14 @@ impl CompiledModule for Module {
wasmer_runtime_core::compile_with(bytes, &compiler::default_compiler())
}

fn new_with_compiler(
bytes: impl AsRef<[u8]>,
compiler: Box<dyn compiler::Compiler>,
Copy link
Contributor

Choose a reason for hiding this comment

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

Here too

@@ -285,7 +285,7 @@ pub unsafe extern "C" fn wasmer_module_deserialize(
let serialized_module: &[u8] = &*(serialized_module as *const &[u8]);

match Artifact::deserialize(serialized_module) {
Ok(artifact) => match load_cache_with(artifact, &default_compiler()) {
Ok(artifact) => match load_cache_with(artifact, &*default_compiler()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not 100% but it may be possible to just do default_compiler() here; though if we revert it back to impl Compiler return value, then we'll still need that &

Copy link
Member Author

Choose a reason for hiding this comment

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

I tried with both (default_compiler() and &default_compiler()) and Rust complained.

src/commands/run.rs Show resolved Hide resolved
tests/custom/multiple-traps.wast Show resolved Hide resolved
tests/test-generator/src/lib.rs Outdated Show resolved Hide resolved
return None;
}

// Ignore files starting with `.`, which could be editor temporary files
Copy link
Contributor

Choose a reason for hiding this comment

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

There are crates that do file globbing that respect .gitignores I think 🤔 , might be simpler

Copy link
Member Author

Choose a reason for hiding this comment

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

Just looked into it. The most obvious crate is:
https://crates.io/crates/ignore

But I think it's not trivial (as a few mins of work) to add it. If required we can add it in a PR apart. The simple solution works for now though :)

tests/test-generator/src/processors.rs Outdated Show resolved Hide resolved
tests/test-generator/src/processors.rs Outdated Show resolved Hide resolved
tests/wasi_serialization.rs Outdated Show resolved Hide resolved
@syrusakbary
Copy link
Member Author

bors try

bors bot added a commit that referenced this pull request Apr 16, 2020
@bors
Copy link
Contributor

bors bot commented Apr 16, 2020

try

Build succeeded:

@syrusakbary syrusakbary changed the title Refactor Test Refactor Apr 16, 2020
@syrusakbary
Copy link
Member Author

bors r+

bors bot added a commit that referenced this pull request Apr 16, 2020
1382: Test Refactor r=syrusakbary a=syrusakbary

# Description

This PR is the continuation of #1380.
It refactors our testing infrastructure based on various points:
* There is no longer a "default compiler" on tests
* Tests are automatically generated for: emscripten and wasi
* It accelerates testing into multiple threads when possible (with the exception of the llvm backend)
* It automatically detects the backends available in the host

Summary of changes:
* [x] Removed all extra logic for test creation in emscripten test generator
* [x] Removed all extra logic for test creation in the wasi test generator
* [x] Divided wasmer wast test in different files (under `tests/custom/`)
* [x] Refactored trap asserts using the wast format
* [x] Improved the build script by adding emscripten and wasi test generators (separated from build)
* [x] Improved WASI errors to be Rust error types (by deriving from `thiserror::Error`)
* [x] Fixed toolchain error creation
* [x] Removed leaking of testing logic from generators into build
* [x] Refactored import tests to be compatible with multiple backends
* [x] Improved wasmer binary to work even when no backends are set (useful for testing without any backend available).
* [x] Removed assumption that Cranelift will be the default in the `wasmer` binary
* [x] Migrated middleware

# Review

- [x] Add a short description of the the change to the CHANGELOG.md file


Co-authored-by: Syrus <[email protected]>
Co-authored-by: Syrus Akbary <[email protected]>
@bors
Copy link
Contributor

bors bot commented Apr 16, 2020

Build failed:

@syrusakbary
Copy link
Member Author

bors r+

@bors
Copy link
Contributor

bors bot commented Apr 16, 2020

Build succeeded:

  • wasmerio.wasmer

@bors bors bot merged commit e19dbbe into master Apr 16, 2020
@bors bors bot deleted the test-refactor-2 branch April 16, 2020 23:45
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.

4 participants