Migrate wasm-bindgen classes test to wasm

This commit is contained in:
Alex Crichton
2018-08-04 11:52:21 -07:00
parent df7bcc4e03
commit 57fd1dedd6
5 changed files with 483 additions and 760 deletions

View File

@ -1,759 +0,0 @@
use super::project;
#[test]
fn simple() {
project()
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct Foo {
contents: u32,
}
#[wasm_bindgen]
impl Foo {
#[wasm_bindgen(constructor)]
pub fn new() -> Foo {
Foo::with_contents(0)
}
pub fn with_contents(a: u32) -> Foo {
Foo { contents: a }
}
pub fn add(&mut self, amt: u32) -> u32 {
self.contents += amt;
self.contents
}
pub fn consume(self) -> u32 {
self.contents
}
}
"#,
)
.file(
"test.js",
r#"
import * as assert from "assert";
import { Foo } from "./out";
export function test() {
const r = Foo.new();
assert.strictEqual(r.add(0), 0);
assert.strictEqual(r.add(1), 1);
assert.strictEqual(r.add(1), 2);
r.add(2);
assert.strictEqual(r.consume(), 4);
assert.throws(() => r.free(), /null pointer passed to rust/);
const r2 = Foo.with_contents(10);
assert.strictEqual(r2.add(1), 11);
assert.strictEqual(r2.add(2), 13);
assert.strictEqual(r2.add(3), 16);
r2.free();
const r3 = new Foo();
assert.strictEqual(r3.add(42), 42);
r3.free();
}
"#,
)
.test();
}
#[test]
fn strings() {
project()
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct Foo {
name: u32,
}
#[wasm_bindgen]
pub struct Bar {
contents: String,
}
#[wasm_bindgen]
impl Foo {
pub fn new() -> Foo {
Foo { name: 0 }
}
pub fn set(&mut self, amt: u32) {
self.name = amt;
}
pub fn bar(&self, mix: &str) -> Bar {
Bar { contents: format!("foo-{}-{}", mix, self.name) }
}
}
#[wasm_bindgen]
impl Bar {
pub fn name(&self) -> String {
self.contents.clone()
}
}
"#,
)
.file(
"test.js",
r#"
import * as assert from "assert";
import { Foo } from "./out";
export function test() {
const r = Foo.new();
r.set(3);
let bar = r.bar('baz');
r.free();
assert.strictEqual(bar.name(), "foo-baz-3");
bar.free();
}
"#,
)
.test();
}
#[test]
fn exceptions() {
project()
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct A {
}
#[wasm_bindgen]
impl A {
pub fn new() -> A {
A {}
}
pub fn foo(&self, _: &A) {
}
pub fn bar(&mut self, _: &mut A) {
}
}
#[wasm_bindgen]
pub struct B {
}
#[wasm_bindgen]
impl B {
pub fn new() -> B {
B {}
}
}
"#,
)
.file(
"test.js",
r#"
import * as assert from "assert";
import { A, B } from "./out";
export function test() {
assert.throws(() => new A(), /cannot invoke `new` directly/);
let a = A.new();
a.free();
assert.throws(() => a.free(), /null pointer passed to rust/);
let b = A.new();
b.foo(b);
assert.throws(() => b.bar(b), /recursive use of an object/);
let c = A.new();
let d = B.new();
assert.throws(() => c.foo(d), /expected instance of A/);
d.free();
c.free();
};
"#,
)
.test();
}
#[test]
fn pass_one_to_another() {
project()
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct A {}
#[wasm_bindgen]
impl A {
pub fn new() -> A {
A {}
}
pub fn foo(&self, _other: &B) {
}
pub fn bar(&self, _other: B) {
}
}
#[wasm_bindgen]
pub struct B {}
#[wasm_bindgen]
impl B {
pub fn new() -> B {
B {}
}
}
"#,
)
.file(
"test.js",
r#"
import { A, B } from "./out";
export function test() {
let a = A.new();
let b = B.new();
a.foo(b);
a.bar(b);
a.free();
}
"#,
)
.test();
}
#[test]
fn pass_into_js() {
project()
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct Foo(i32);
#[wasm_bindgen]
impl Foo {
pub fn inner(&self) -> i32 {
self.0
}
}
#[wasm_bindgen(module = "./test")]
extern {
fn take_foo(foo: Foo);
}
#[wasm_bindgen]
pub fn run() {
take_foo(Foo(13));
}
"#,
)
.file(
"test.js",
r#"
import { run, Foo } from "./out";
import * as assert from "assert";
export function take_foo(foo) {
assert.strictEqual(foo.inner(), 13);
foo.free();
assert.throws(() => foo.free(), /null pointer passed to rust/);
}
export function test() {
run();
}
"#,
)
.test();
}
#[test]
fn issue_27() {
project()
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct Context {}
#[wasm_bindgen]
impl Context {
pub fn parse(&self, _expr: &str) -> Expr {
panic!()
}
pub fn eval(&self, _expr: &Expr) -> f64 {
panic!()
}
pub fn set(&mut self, _var: &str, _val: f64) {
panic!()
}
}
#[wasm_bindgen]
pub struct Expr {}
#[wasm_bindgen]
pub fn context() -> Context {
Context {}
}
"#,
)
.file(
"test.js",
r#"
import { context } from "./out";
export function test() {
context();
}
"#,
)
.test();
}
#[test]
fn pass_into_js_as_js_class() {
project()
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct Foo(i32);
#[wasm_bindgen]
impl Foo {
pub fn inner(&self) -> i32 {
self.0
}
}
#[wasm_bindgen(module = "./test")]
extern {
fn take_foo(foo: JsValue);
}
#[wasm_bindgen]
pub fn run() {
take_foo(Foo(13).into());
}
"#,
)
.file(
"test.js",
r#"
import { run, Foo } from "./out";
import * as assert from "assert";
export function take_foo(foo) {
assert.ok(foo instanceof Foo);
assert.strictEqual(foo.inner(), 13);
foo.free();
}
export function test() {
run();
}
"#,
)
.test();
}
#[test]
fn constructors() {
project()
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn cross_item_construction() -> Bar {
Bar::other_name(7, 8)
}
#[wasm_bindgen]
pub struct Foo {
number: u32,
}
#[wasm_bindgen]
impl Foo {
#[wasm_bindgen(constructor)]
pub fn new(number: u32) -> Foo {
Foo { number }
}
pub fn get_number(&self) -> u32 {
self.number
}
}
#[wasm_bindgen]
pub struct Bar {
number: u32,
number2: u32,
}
#[wasm_bindgen]
impl Bar {
#[wasm_bindgen(constructor)]
pub fn other_name(number: u32, number2: u32) -> Bar {
Bar { number, number2 }
}
pub fn get_sum(&self) -> u32 {
self.number + self.number2
}
}
"#,
)
.file(
"test.js",
r#"
import * as assert from "assert";
import { Foo, Bar, cross_item_construction } from "./out";
export function test() {
const foo = new Foo(1);
assert.strictEqual(foo.get_number(), 1);
foo.free();
const foo2 = Foo.new(2);
assert.strictEqual(foo2.get_number(), 2);
foo2.free();
const bar = new Bar(3, 4);
assert.strictEqual(bar.get_sum(), 7);
bar.free();
const bar2 = Bar.other_name(5, 6);
assert.strictEqual(bar2.get_sum(), 11);
bar2.free();
assert.strictEqual(cross_item_construction().get_sum(), 15);
}
"#,
)
.test();
}
#[test]
fn empty_structs() {
project()
.debug(false)
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct MissingClass {}
#[wasm_bindgen]
pub struct Other {}
#[wasm_bindgen]
impl Other { pub fn return_a_value() -> MissingClass { MissingClass {} } }
"#,
)
.file(
"test.js",
r#"
import { Other } from "./out";
export function test() {
Other.return_a_value();
}
"#,
)
.test();
}
#[test]
fn public_fields() {
project()
.debug(false)
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
#[derive(Default)]
pub struct Foo {
pub a: u32,
pub b: f32,
pub c: f64,
pub d: i32,
}
#[wasm_bindgen]
impl Foo {
pub fn new() -> Foo {
Foo::default()
}
}
"#,
)
.file(
"test.js",
r#"
import { Foo } from "./out";
import * as assert from "assert";
export function test() {
const a = Foo.new();
assert.strictEqual(a.a, 0);
a.a = 3;
assert.strictEqual(a.a, 3);
assert.strictEqual(a.b, 0);
a.b = 7;
assert.strictEqual(a.b, 7);
assert.strictEqual(a.c, 0);
a.c = 8;
assert.strictEqual(a.c, 8);
assert.strictEqual(a.d, 0);
a.d = 3.3;
assert.strictEqual(a.d, 3);
}
"#,
)
.test();
}
#[test]
fn using_self() {
project()
.debug(false)
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct Foo {
}
#[wasm_bindgen]
impl Foo {
pub fn new() -> Self {
Foo {}
}
}
"#,
)
.file(
"test.js",
r#"
import { Foo } from "./out";
export function test() {
Foo.new().free();
}
"#,
)
.test();
}
#[test]
fn readonly_fields() {
project()
.debug(false)
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
#[derive(Default)]
pub struct Foo {
#[wasm_bindgen(readonly)]
pub a: u32,
}
#[wasm_bindgen]
impl Foo {
pub fn new() -> Foo {
Foo::default()
}
}
"#,
)
.file(
"test.js",
r#"
import { Foo } from "./out";
import * as assert from "assert";
export function test() {
const a = Foo.new();
assert.strictEqual(a.a, 0);
assert.throws(() => a.a = 3, /has only a getter/);
a.free();
}
"#,
)
.test();
}
#[test]
fn double_consume() {
project()
.file("src/lib.rs", r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct Foo { }
#[wasm_bindgen]
impl Foo {
#[wasm_bindgen(constructor)]
pub fn new() -> Foo {
Foo {}
}
pub fn consume(self, other: Foo) {
drop(other);
}
}
"#)
.file("test.js", r#"
import * as assert from "assert";
import { Foo } from "./out";
export function test() {
const r = Foo.new();
assert.throws(() => r.consume(r), /Attempt to use a moved value/);
}
"#)
.test();
}
#[test]
fn rename_function_for_js() {
project()
.file("src/lib.rs", r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct Foo { }
#[wasm_bindgen]
impl Foo {
#[wasm_bindgen(constructor)]
pub fn new() -> Foo {
let f = Foo {};
f.foo();
return f
}
#[wasm_bindgen(js_name = bar)]
pub fn foo(&self) {
}
}
#[wasm_bindgen(js_name = js_foo)]
pub fn foo() {}
#[wasm_bindgen]
pub fn bar() {
foo();
}
"#)
.file("test.js", r#"
import { Foo, js_foo, bar } from "./out";
export function test() {
Foo.new().bar();
js_foo();
bar();
}
"#)
.test();
}

View File

@ -4,7 +4,6 @@ extern crate wasm_bindgen_test_project_builder as project_builder;
use project_builder::{project, run};
mod classes;
mod closures;
mod comments;
mod dependencies;

128
tests/wasm/classes.js Normal file
View File

@ -0,0 +1,128 @@
const assert = require('assert');
const wasm = require('wasm-bindgen-test.js');
exports.test_simple = function() {
const r = wasm.ClassesSimple.new();
assert.strictEqual(r.add(0), 0);
assert.strictEqual(r.add(1), 1);
assert.strictEqual(r.add(1), 2);
r.add(2);
assert.strictEqual(r.consume(), 4);
assert.throws(() => r.free(), /null pointer passed to rust/);
const r2 = wasm.ClassesSimple.with_contents(10);
assert.strictEqual(r2.add(1), 11);
assert.strictEqual(r2.add(2), 13);
assert.strictEqual(r2.add(3), 16);
r2.free();
const r3 = new wasm.ClassesSimple();
assert.strictEqual(r3.add(42), 42);
r3.free();
};
exports.test_strings = function() {
const r = wasm.ClassesStrings1.new();
r.set(3);
let bar = r.bar('baz');
r.free();
assert.strictEqual(bar.name(), "foo-baz-3");
bar.free();
};
exports.test_exceptions = function() {
assert.throws(() => new wasm.ClassesExceptions1(), /cannot invoke `new` directly/);
let a = wasm.ClassesExceptions1.new();
a.free();
assert.throws(() => a.free(), /null pointer passed to rust/);
let b = wasm.ClassesExceptions1.new();
b.foo(b);
assert.throws(() => b.bar(b), /recursive use of an object/);
let c = wasm.ClassesExceptions1.new();
let d = wasm.ClassesExceptions2.new();
assert.throws(() => c.foo(d), /expected instance of ClassesExceptions1/);
d.free();
c.free();
};
exports.test_pass_one_to_another = function() {
let a = wasm.ClassesPassA.new();
let b = wasm.ClassesPassB.new();
a.foo(b);
a.bar(b);
a.free();
};
exports.take_class = function(foo) {
assert.strictEqual(foo.inner(), 13);
foo.free();
assert.throws(() => foo.free(), /null pointer passed to rust/);
};
exports.test_constructors = function() {
const foo = new wasm.ConstructorsFoo(1);
assert.strictEqual(foo.get_number(), 1);
foo.free();
const foo2 = wasm.ConstructorsFoo.new(2);
assert.strictEqual(foo2.get_number(), 2);
foo2.free();
const bar = new wasm.ConstructorsBar(3, 4);
assert.strictEqual(bar.get_sum(), 7);
bar.free();
const bar2 = wasm.ConstructorsBar.other_name(5, 6);
assert.strictEqual(bar2.get_sum(), 11);
bar2.free();
assert.strictEqual(wasm.cross_item_construction().get_sum(), 15);
};
exports.test_empty_structs = function() {
wasm.OtherEmpty.return_a_value();
};
exports.test_public_fields = function() {
const a = wasm.PublicFields.new();
assert.strictEqual(a.a, 0);
a.a = 3;
assert.strictEqual(a.a, 3);
assert.strictEqual(a.b, 0);
a.b = 7;
assert.strictEqual(a.b, 7);
assert.strictEqual(a.c, 0);
a.c = 8;
assert.strictEqual(a.c, 8);
assert.strictEqual(a.d, 0);
a.d = 3.3;
assert.strictEqual(a.d, 3);
};
exports.test_using_self = function() {
wasm.UseSelf.new().free();
};
exports.test_readonly_fields = function() {
const a = wasm.Readonly.new();
assert.strictEqual(a.a, 0);
a.a = 3;
assert.strictEqual(a.a, 0);
a.free();
};
exports.test_double_consume = function() {
const r = wasm.DoubleConsume.new();
assert.throws(() => r.consume(r), /Attempt to use a moved value/);
}
exports.test_js_rename = function() {
wasm.JsRename.new().bar();
wasm.classes_foo();
};

354
tests/wasm/classes.rs Normal file
View File

@ -0,0 +1,354 @@
use wasm_bindgen_test::*;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "tests/wasm/classes.js", version = "*")]
extern {
fn test_simple();
fn test_strings();
fn test_exceptions();
fn test_pass_one_to_another();
fn take_class(foo: ClassesIntoJs);
#[wasm_bindgen(js_name = take_class)]
fn take_class_as_jsvalue(foo: JsValue);
fn test_constructors();
fn test_empty_structs();
fn test_public_fields();
fn test_using_self();
fn test_readonly_fields();
fn test_double_consume();
fn test_js_rename();
}
#[wasm_bindgen_test]
fn simple() {
test_simple();
}
#[wasm_bindgen]
pub struct ClassesSimple {
contents: u32,
}
#[wasm_bindgen]
impl ClassesSimple {
#[wasm_bindgen(constructor)]
pub fn new() -> ClassesSimple {
ClassesSimple::with_contents(0)
}
pub fn with_contents(a: u32) -> ClassesSimple {
ClassesSimple { contents: a }
}
pub fn add(&mut self, amt: u32) -> u32 {
self.contents += amt;
self.contents
}
pub fn consume(self) -> u32 {
self.contents
}
}
#[wasm_bindgen_test]
fn strings() {
test_strings()
}
#[wasm_bindgen]
pub struct ClassesStrings1 {
name: u32,
}
#[wasm_bindgen]
pub struct ClassesStrings2 {
contents: String,
}
#[wasm_bindgen]
impl ClassesStrings1 {
pub fn new() -> ClassesStrings1 {
ClassesStrings1 { name: 0 }
}
pub fn set(&mut self, amt: u32) {
self.name = amt;
}
pub fn bar(&self, mix: &str) -> ClassesStrings2 {
ClassesStrings2 { contents: format!("foo-{}-{}", mix, self.name) }
}
}
#[wasm_bindgen]
impl ClassesStrings2 {
pub fn name(&self) -> String {
self.contents.clone()
}
}
#[wasm_bindgen_test]
fn exceptions() {
test_exceptions();
}
#[wasm_bindgen]
pub struct ClassesExceptions1 {
}
#[wasm_bindgen]
impl ClassesExceptions1 {
pub fn new() -> ClassesExceptions1 {
ClassesExceptions1 {}
}
pub fn foo(&self, _: &ClassesExceptions1) {
}
pub fn bar(&mut self, _: &mut ClassesExceptions1) {
}
}
#[wasm_bindgen]
pub struct ClassesExceptions2 {
}
#[wasm_bindgen]
impl ClassesExceptions2 {
pub fn new() -> ClassesExceptions2 {
ClassesExceptions2 {}
}
}
#[wasm_bindgen_test]
fn pass_one_to_another() {
test_pass_one_to_another();
}
#[wasm_bindgen]
pub struct ClassesPassA {}
#[wasm_bindgen]
impl ClassesPassA {
pub fn new() -> ClassesPassA {
ClassesPassA {}
}
pub fn foo(&self, _other: &ClassesPassB) {
}
pub fn bar(&self, _other: ClassesPassB) {
}
}
#[wasm_bindgen]
pub struct ClassesPassB {}
#[wasm_bindgen]
impl ClassesPassB {
pub fn new() -> ClassesPassB {
ClassesPassB {}
}
}
#[wasm_bindgen_test]
fn pass_into_js() {
take_class(ClassesIntoJs(13));
}
#[wasm_bindgen]
pub struct ClassesIntoJs(i32);
#[wasm_bindgen]
impl ClassesIntoJs {
pub fn inner(&self) -> i32 {
self.0
}
}
#[wasm_bindgen]
pub struct Issue27Context {}
#[wasm_bindgen]
impl Issue27Context {
pub fn parse(&self, _expr: &str) -> Issue27Expr {
panic!()
}
pub fn eval(&self, _expr: &Issue27Expr) -> f64 {
panic!()
}
pub fn set(&mut self, _var: &str, _val: f64) {
panic!()
}
}
#[wasm_bindgen]
pub struct Issue27Expr {}
#[wasm_bindgen_test]
fn pass_into_js_as_js_class() {
take_class_as_jsvalue(ClassesIntoJs(13).into());
}
#[wasm_bindgen_test]
fn constructors() {
test_constructors();
}
#[wasm_bindgen]
pub fn cross_item_construction() -> ConstructorsBar {
ConstructorsBar::other_name(7, 8)
}
#[wasm_bindgen]
pub struct ConstructorsFoo {
number: u32,
}
#[wasm_bindgen]
impl ConstructorsFoo {
#[wasm_bindgen(constructor)]
pub fn new(number: u32) -> ConstructorsFoo {
ConstructorsFoo { number }
}
pub fn get_number(&self) -> u32 {
self.number
}
}
#[wasm_bindgen]
pub struct ConstructorsBar {
number: u32,
number2: u32,
}
#[wasm_bindgen]
impl ConstructorsBar {
#[wasm_bindgen(constructor)]
pub fn other_name(number: u32, number2: u32) -> ConstructorsBar {
ConstructorsBar { number, number2 }
}
pub fn get_sum(&self) -> u32 {
self.number + self.number2
}
}
#[wasm_bindgen_test]
fn empty_structs() {
test_empty_structs();
}
#[wasm_bindgen]
pub struct MissingClass {}
#[wasm_bindgen]
pub struct OtherEmpty {}
#[wasm_bindgen]
impl OtherEmpty {
pub fn return_a_value() -> MissingClass { MissingClass {} }
}
#[wasm_bindgen_test]
fn public_fields() {
test_public_fields();
}
#[wasm_bindgen]
#[derive(Default)]
pub struct PublicFields {
pub a: u32,
pub b: f32,
pub c: f64,
pub d: i32,
}
#[wasm_bindgen]
impl PublicFields {
pub fn new() -> PublicFields {
PublicFields::default()
}
}
#[wasm_bindgen_test]
fn using_self() {
test_using_self();
}
#[wasm_bindgen]
pub struct UseSelf {
}
#[wasm_bindgen]
impl UseSelf {
pub fn new() -> Self {
UseSelf {}
}
}
#[wasm_bindgen_test]
fn readonly_fields() {
test_readonly_fields();
}
#[wasm_bindgen]
#[derive(Default)]
pub struct Readonly {
#[wasm_bindgen(readonly)]
pub a: u32,
}
#[wasm_bindgen]
impl Readonly {
pub fn new() -> Readonly {
Readonly::default()
}
}
#[wasm_bindgen_test]
fn double_consume() {
test_double_consume();
}
#[wasm_bindgen]
pub struct DoubleConsume { }
#[wasm_bindgen]
impl DoubleConsume {
#[wasm_bindgen(constructor)]
pub fn new() -> DoubleConsume {
DoubleConsume {}
}
pub fn consume(self, other: DoubleConsume) {
drop(other);
}
}
#[wasm_bindgen_test]
fn rename_function_for_js() {
test_js_rename();
foo();
}
#[wasm_bindgen]
pub struct JsRename { }
#[wasm_bindgen]
impl JsRename {
#[wasm_bindgen(constructor)]
pub fn new() -> JsRename {
let f = JsRename {};
f.foo();
return f
}
#[wasm_bindgen(js_name = bar)]
pub fn foo(&self) {
}
}
#[wasm_bindgen(js_name = classes_foo)]
pub fn foo() {}

View File

@ -6,5 +6,6 @@ extern crate wasm_bindgen;
pub mod api;
pub mod char;
pub mod classes;
pub mod option;
pub mod optional_primitives;