Skip to content

Commit 45b20ea

Browse files
authored
Merge pull request #13 from yoshuawuyts/pch/enable_ci_and_write_tests
Enable CI and write some tests that execute with wasmtime
2 parents f25af48 + 45eaa3b commit 45b20ea

File tree

16 files changed

+409
-26
lines changed

16 files changed

+409
-26
lines changed

.github/workflows/ci.yaml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,36 @@ env:
1111
RUSTFLAGS: -Dwarnings
1212

1313
jobs:
14+
build_and_test:
15+
name: Build and test
16+
runs-on: ${{ matrix.os }}
17+
strategy:
18+
matrix:
19+
os: [ubuntu-latest, windows-latest, macOS-latest]
20+
rust: [stable]
21+
22+
steps:
23+
- uses: actions/checkout@master
24+
25+
- name: Install ${{ matrix.rust }}
26+
uses: actions-rs/toolchain@v1
27+
with:
28+
toolchain: ${{ matrix.rust }}
29+
target: wasm32-wasip2
30+
override: true
31+
32+
- name: check
33+
uses: actions-rs/cargo@v1
34+
with:
35+
command: check
36+
args: --all --bins --examples
37+
38+
- name: tests
39+
uses: actions-rs/cargo@v1
40+
with:
41+
command: test
42+
args: --all
43+
1444
check_fmt_and_docs:
1545
name: Checking fmt and docs
1646
runs-on: ubuntu-latest

Cargo.toml

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
[package]
22
name = "wstd"
3-
version = "0.4.0"
4-
license = "MIT OR Apache-2.0 OR Apache-2.0 WITH LLVM-exception"
3+
version.workspace = true
4+
license.workspace = true
55
repository = "https://github.com/yoshuawuyts/wstd"
66
documentation = "https://docs.rs/wstd"
77
description = "An async standard library for Wasm Components and WASI 0.2"
88
readme = "README.md"
9-
edition = "2021"
10-
resolver = "2"
9+
edition.workspace = true
1110
keywords = ["WebAssembly", "async", "stdlib", "Components"]
1211
categories = []
1312
authors = [
@@ -17,8 +16,46 @@ authors = [
1716
[features]
1817

1918
[dependencies]
19+
slab.workspace = true
20+
url.workspace = true
21+
wasi.workspace = true
22+
wstd-macro.workspace = true
23+
24+
[dev-dependencies]
25+
anyhow.workspace = true
26+
serde_json.workspace = true
27+
test-programs-artifacts.workspace = true
28+
wasmtime.workspace = true
29+
wasmtime-wasi.workspace = true
30+
wasmtime-wasi-http.workspace = true
31+
32+
[workspace]
33+
members = [
34+
"macro",
35+
"test-programs",
36+
"test-programs/artifacts",
37+
]
38+
resolver = "2"
39+
40+
[workspace.package]
41+
version = "0.4.0"
42+
edition = "2021"
43+
license = "MIT OR Apache-2.0 OR Apache-2.0 WITH LLVM-exception"
44+
45+
[workspace.dependencies]
46+
anyhow = "1"
47+
cargo_metadata = "0.18.1"
48+
heck = "0.5"
49+
quote = "1.0"
50+
serde_json = "1"
2051
slab = "0.4.9"
52+
syn = "2.0"
53+
test-programs = { path = "test-programs" }
54+
test-programs-artifacts = { path = "test-programs/artifacts" }
2155
url = "2.5.0"
2256
wasi = "0.13.1"
23-
24-
[dev-dependencies]
57+
wasmtime = "26"
58+
wasmtime-wasi = "26"
59+
wasmtime-wasi-http = "26"
60+
wstd = { path = "." }
61+
wstd-macro = { path = "macro" }

examples/http_get.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
use std::error::Error;
2+
use wstd::http::{Client, Method, Request, Url};
3+
use wstd::io::AsyncRead;
4+
5+
#[wstd::main]
6+
async fn main() -> Result<(), Box<dyn Error>> {
7+
let request = Request::new(Method::Get, Url::parse("https://postman-echo.com/get")?);
8+
let mut response = Client::new().send(request).await?;
9+
10+
let content_type = response
11+
.headers()
12+
.get(&"content-type".into())
13+
.ok_or_else(|| "response expected to have content-type header")?;
14+
assert_eq!(content_type.len(), 1, "one header value for content-type");
15+
assert_eq!(content_type[0], b"application/json; charset=utf-8");
16+
17+
// Would much prefer read_to_end here:
18+
let mut body_buf = vec![0; 4096];
19+
let body_len = response.body().read(&mut body_buf).await?;
20+
body_buf.truncate(body_len);
21+
22+
let val: serde_json::Value = serde_json::from_slice(&body_buf)?;
23+
let body_url = val
24+
.get("url")
25+
.ok_or_else(|| "body json has url")?
26+
.as_str()
27+
.ok_or_else(|| "body json url is str")?;
28+
assert!(
29+
body_url.contains("postman-echo.com/get"),
30+
"expected body url to contain the authority and path, got: {body_url}"
31+
);
32+
33+
Ok(())
34+
}

examples/tcp_echo_server.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
use wstd::io;
2+
use wstd::iter::AsyncIterator;
3+
use wstd::net::TcpListener;
4+
5+
#[wstd::main]
6+
async fn main() -> io::Result<()> {
7+
let listener = TcpListener::bind("127.0.0.1:8080").await?;
8+
println!("Listening on {}", listener.local_addr()?);
9+
println!("type `nc localhost 8080` to create a TCP client");
10+
11+
let mut incoming = listener.incoming();
12+
while let Some(stream) = incoming.next().await {
13+
let stream = stream?;
14+
println!("Accepted from: {}", stream.peer_addr()?);
15+
io::copy(&stream, &stream).await?;
16+
}
17+
Ok(())
18+
}

macro/Cargo.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
name = "wstd-macro"
3+
version.workspace = true
4+
edition.workspace = true
5+
license.workspace = true
6+
7+
[lib]
8+
proc-macro = true
9+
10+
[dependencies]
11+
syn = { workspace = true, features = ["full"] }
12+
quote.workspace = true

macro/src/lib.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
use proc_macro::TokenStream;
2+
use quote::{quote, quote_spanned};
3+
use syn::{parse_macro_input, spanned::Spanned, ItemFn};
4+
5+
#[proc_macro_attribute]
6+
pub fn attr_macro_main(_attr: TokenStream, item: TokenStream) -> TokenStream {
7+
let input = parse_macro_input!(item as ItemFn);
8+
9+
if input.sig.asyncness.is_none() {
10+
return quote_spanned! { input.sig.fn_token.span()=>
11+
compile_error!("fn must be `async fn`");
12+
}
13+
.into();
14+
}
15+
16+
if input.sig.ident != "main" {
17+
return quote_spanned! { input.sig.ident.span()=>
18+
compile_error!("only `async fn main` can be used for #[wstd::main]");
19+
}
20+
.into();
21+
}
22+
23+
if !input.sig.inputs.is_empty() {
24+
return quote_spanned! { input.sig.inputs.span()=>
25+
compile_error!("arguments to main are not supported");
26+
}
27+
.into();
28+
}
29+
let attrs = input.attrs;
30+
let output = input.sig.output;
31+
let block = input.block;
32+
quote! {
33+
pub fn main() #output {
34+
35+
#(#attrs)*
36+
async fn __run() #output {
37+
#block
38+
}
39+
40+
::wstd::runtime::block_on(async {
41+
__run().await
42+
})
43+
}
44+
}
45+
.into()
46+
}

rust-toolchain.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[toolchain]
2+
channel = "1.82.0"
3+
targets = ["wasm32-wasip2"]

src/lib.rs

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,14 @@
1212
//!
1313
//! **TCP echo server**
1414
//!
15-
//! ```rust
16-
//! use wstd::io;
17-
//! use wstd::iter::AsyncIterator;
18-
//! use wstd::net::TcpListener;
19-
//! use wstd::runtime::block_on;
15+
//! ```rust,no_run
16+
#![doc = include_str!("../examples/tcp_echo_server.rs")]
17+
//! ```
2018
//!
21-
//! fn main() -> io::Result<()> {
22-
//! block_on(async move {
23-
//! let listener = TcpListener::bind("127.0.0.1:8080").await?;
24-
//! println!("Listening on {}", listener.local_addr()?);
25-
//! println!("type `nc localhost 8080` to create a TCP client");
19+
//! **HTTP Client**
2620
//!
27-
//! let mut incoming = listener.incoming();
28-
//! while let Some(stream) = incoming.next().await {
29-
//! let stream = stream?;
30-
//! println!("Accepted from: {}", stream.peer_addr()?);
31-
//! io::copy(&stream, &stream).await?;
32-
//! }
33-
//! Ok(())
34-
//! })
35-
//! }
21+
//! ```rust,no_run
22+
#![doc = include_str!("../examples/http_get.rs")]
3623
//! ```
3724
//!
3825
//! # Design Decisions
@@ -64,3 +51,5 @@ pub mod net;
6451
pub mod rand;
6552
pub mod runtime;
6653
pub mod time;
54+
55+
pub use wstd_macro::attr_macro_main as main;

test-programs/Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "test-programs"
3+
version = "0.1.0"
4+
edition = "2021"
5+
publish = false
6+
7+
[dependencies]
8+
serde_json.workspace = true
9+
wstd.workspace = true

test-programs/artifacts/Cargo.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
name = "test-programs-artifacts"
3+
version = "0.1.0"
4+
edition.workspace = true
5+
license.workspace = true
6+
publish = false
7+
8+
[dependencies]
9+
10+
[build-dependencies]
11+
cargo_metadata.workspace = true
12+
heck.workspace = true

0 commit comments

Comments
 (0)