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

Update conformance tests #96

Merged
merged 3 commits into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions conformance-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ edition = "2021"

[dependencies]
anyhow = "1.0"
conformance-tests = { git = "https://github.com/fermyon/conformance-tests" }
test-environment = { git = "https://github.com/fermyon/conformance-tests" }
conformance-tests = { git = "https://github.com/fermyon/conformance-tests", branch = "main" }
test-environment = { git = "https://github.com/fermyon/conformance-tests", branch = "main" }
spin-test = { path = ".." }
wasmtime = "21.0"
wasmtime-wasi = "21.0"
76 changes: 40 additions & 36 deletions conformance-tests/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,49 +7,53 @@ use runtime::SpinTest;
const HTTP_PORT: u16 = 1234;

fn main() -> anyhow::Result<()> {
let tests_dir = conformance_tests::download_tests()?;
conformance_tests::run_tests_from("../../conformance-tests/conformance-tests", |test| {
run_test(test)
})
}

for test in conformance_tests::tests(&tests_dir)? {
println!("Test: {}", test.name);
let mut manifest =
test_environment::manifest_template::EnvTemplate::from_file(&test.manifest)?;
let env_config = test_environment::TestEnvironmentConfig {
create_runtime: Box::new(|_env| {
manifest.substitute_value("port", |port| {
(port == "80").then(|| HTTP_PORT.to_string())
})?;
SpinTest::new(manifest.into_contents(), test.component)
}),
// Services are not needed in `spin-test` since everything stays in the guest
services_config: test_environment::services::ServicesConfig::none(),
};
let mut env = test_environment::TestEnvironment::up(env_config, |_| Ok(())).unwrap();
for precondition in &test.config.preconditions {
match precondition {
conformance_tests::config::Precondition::HttpEcho => {
env.runtime_mut()
.set_echo_response(format!("http://localhost:{HTTP_PORT}").as_str())?;
}
conformance_tests::config::Precondition::KeyValueStore(_) => {}
fn run_test(test: conformance_tests::Test) -> Result<(), anyhow::Error> {
let mut manifest = test_environment::manifest_template::EnvTemplate::from_file(&test.manifest)?;
let env_config = test_environment::TestEnvironmentConfig {
create_runtime: Box::new(|_env| {
manifest.substitute_value("port", |port| substitution("port", port))?;
SpinTest::new(manifest.into_contents(), test.component)
}),
// Services are not needed in `spin-test` since everything stays in the guest
services_config: test_environment::services::ServicesConfig::none(),
};
let mut env = test_environment::TestEnvironment::up(env_config, |_| Ok(()))?;
for precondition in &test.config.preconditions {
match precondition {
conformance_tests::config::Precondition::HttpEcho => {
env.runtime_mut()
.set_echo_response(format!("http://localhost:{HTTP_PORT}").as_str())?;
}
conformance_tests::config::Precondition::TcpEcho => {}
conformance_tests::config::Precondition::KeyValueStore(_) => {}
}
for invocation in test.config.invocations {
let conformance_tests::config::Invocation::Http(mut invocation) = invocation;
invocation
.request
.substitute(|key, value| {
Ok(match (key, value) {
("port", "80") => Some(HTTP_PORT.to_string()),
_ => None,
})
})
.unwrap();
invocation.run(|request| env.runtime_mut().make_http_request(request))?;
}
}
for invocation in test.config.invocations {
let conformance_tests::config::Invocation::Http(mut invocation) = invocation;
invocation
.request
.substitute(|key, value| Ok(substitution(key, value)))?;

invocation.run(|request| env.runtime_mut().make_http_request(request))?;
}

Ok(())
}

/// When encountering a magic key-value pair, substitute the value with a different value.
fn substitution(key: &str, value: &str) -> Option<String> {
match (key, value) {
("port", "80") => Some(HTTP_PORT.to_string()),
("port", "5000") => Some(5000.to_string()),
_ => None,
}
}

struct StoreData {
manifest: String,
ctx: wasmtime_wasi::WasiCtx,
Expand Down
3 changes: 2 additions & 1 deletion crates/spin-test-virt/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ edition = "2021"

[dependencies]
anyhow = "1.0"
wit-bindgen-rt = { version = "0.25.0", features = ["bitflags"] }
ipnet = "2.9"
spin-expressions = { workspace = true }
spin-manifest = { workspace = true }
spin-outbound-networking = { workspace = true }
spin-serde = { workspace = true }
toml = { workspace = true }
wit-bindgen-rt = { version = "0.25.0", features = ["bitflags"] }


[lib]
Expand Down
14 changes: 8 additions & 6 deletions crates/spin-test-virt/src/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@ use std::sync::{OnceLock, RwLock};
pub struct AppManifest;

impl AppManifest {
/// Returns whether the given URL is allowed by the manifest.
pub fn allows_url(url: &str, scheme: &str) -> anyhow::Result<bool> {
/// Returns the allowed hosts configuration for the current component.
pub fn allowed_hosts() -> anyhow::Result<spin_outbound_networking::AllowedHostsConfig> {
let allowed_outbound_hosts = Self::get_component()
.expect("internal error: component id not yet set")
.normalized_allowed_outbound_hosts()?;
let resolver = spin_expressions::PreparedResolver::default();
let allowed_hosts = spin_outbound_networking::AllowedHostsConfig::parse(
&allowed_outbound_hosts,
&resolver,
)?;
spin_outbound_networking::AllowedHostsConfig::parse(&allowed_outbound_hosts, &resolver)
}

/// Returns whether the given URL is allowed by the manifest.
pub fn allows_url(url: &str, scheme: &str) -> anyhow::Result<bool> {
let allowed_hosts = Self::allowed_hosts()?;
let url = spin_outbound_networking::OutboundUrl::parse(url, scheme)?;
Ok(allowed_hosts.allows(&url))
}
Expand Down
192 changes: 10 additions & 182 deletions crates/spin-test-virt/src/wasi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod filesystem;
pub mod http;
pub mod http_helper;
pub mod io;
mod tcp;

use crate::bindings::exports::wasi;
use crate::Component;
Expand Down Expand Up @@ -152,10 +153,18 @@ impl wasi::cli::exit::Guest for Component {

impl wasi::sockets::instance_network::Guest for Component {
fn instance_network() -> wasi::sockets::instance_network::Network {
todo!()
wasi::sockets::instance_network::Network::new(Network)
}
}

impl wasi::sockets::network::Guest for Component {
type Network = Network;
}

pub struct Network;

impl wasi::sockets::network::GuestNetwork for Network {}

impl wasi::sockets::ip_name_lookup::Guest for Component {
type ResolveAddressStream = ResolveAddressStream;

Expand Down Expand Up @@ -187,187 +196,6 @@ impl wasi::sockets::ip_name_lookup::GuestResolveAddressStream for ResolveAddress
}
}

impl wasi::sockets::network::Guest for Component {
type Network = Network;
}

pub struct Network;

impl wasi::sockets::network::GuestNetwork for Network {}

impl wasi::sockets::tcp::Guest for Component {
type TcpSocket = TcpSocket;
}

pub struct TcpSocket;

impl wasi::sockets::tcp::GuestTcpSocket for TcpSocket {
fn start_bind(
&self,
network: wasi::sockets::tcp::NetworkBorrow<'_>,
local_address: wasi::sockets::tcp::IpSocketAddress,
) -> Result<(), wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn finish_bind(&self) -> Result<(), wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn start_connect(
&self,
network: wasi::sockets::tcp::NetworkBorrow<'_>,
remote_address: wasi::sockets::tcp::IpSocketAddress,
) -> Result<(), wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn finish_connect(
&self,
) -> Result<
(
wasi::sockets::tcp::InputStream,
wasi::sockets::tcp::OutputStream,
),
wasi::sockets::tcp::ErrorCode,
> {
todo!()
}

fn start_listen(&self) -> Result<(), wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn finish_listen(&self) -> Result<(), wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn accept(
&self,
) -> Result<
(
wasi::sockets::tcp::TcpSocket,
wasi::sockets::tcp::InputStream,
wasi::sockets::tcp::OutputStream,
),
wasi::sockets::tcp::ErrorCode,
> {
todo!()
}

fn local_address(
&self,
) -> Result<wasi::sockets::tcp::IpSocketAddress, wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn remote_address(
&self,
) -> Result<wasi::sockets::tcp::IpSocketAddress, wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn is_listening(&self) -> bool {
todo!()
}

fn address_family(&self) -> wasi::sockets::tcp::IpAddressFamily {
todo!()
}

fn set_listen_backlog_size(&self, value: u64) -> Result<(), wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn keep_alive_enabled(&self) -> Result<bool, wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn set_keep_alive_enabled(&self, value: bool) -> Result<(), wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn keep_alive_idle_time(
&self,
) -> Result<wasi::sockets::tcp::Duration, wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn set_keep_alive_idle_time(
&self,
value: wasi::sockets::tcp::Duration,
) -> Result<(), wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn keep_alive_interval(
&self,
) -> Result<wasi::sockets::tcp::Duration, wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn set_keep_alive_interval(
&self,
value: wasi::sockets::tcp::Duration,
) -> Result<(), wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn keep_alive_count(&self) -> Result<u32, wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn set_keep_alive_count(&self, value: u32) -> Result<(), wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn hop_limit(&self) -> Result<u8, wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn set_hop_limit(&self, value: u8) -> Result<(), wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn receive_buffer_size(&self) -> Result<u64, wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn set_receive_buffer_size(&self, value: u64) -> Result<(), wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn send_buffer_size(&self) -> Result<u64, wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn set_send_buffer_size(&self, value: u64) -> Result<(), wasi::sockets::tcp::ErrorCode> {
todo!()
}

fn subscribe(&self) -> wasi::sockets::tcp::Pollable {
todo!()
}

fn shutdown(
&self,
shutdown_type: wasi::sockets::tcp::ShutdownType,
) -> Result<(), wasi::sockets::tcp::ErrorCode> {
todo!()
}
}

impl wasi::sockets::tcp_create_socket::Guest for Component {
fn create_tcp_socket(
address_family: wasi::sockets::tcp_create_socket::IpAddressFamily,
) -> Result<
wasi::sockets::tcp_create_socket::TcpSocket,
wasi::sockets::tcp_create_socket::ErrorCode,
> {
todo!()
}
}

impl wasi::sockets::udp::Guest for Component {
type UdpSocket = UdpSocket;
type IncomingDatagramStream = IncomingDatagramStream;
Expand Down
Loading