Skip to content

Commit

Permalink
Add test for no permission
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Levick <ryan.levick@fermyon.com>
  • Loading branch information
rylev committed Jun 13, 2024
1 parent ea9397f commit 5adb6a0
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 62 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
conformance-tests
71 changes: 41 additions & 30 deletions components/outbound-wasi-http-v0.2.0/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,7 @@ impl incoming_handler::Guest for Component {
.and_then(|v| Url::parse(v).ok())
}) else {
// Otherwise, return a 400 Bad Request response.
let response = OutgoingResponse::new(Headers::new());
response.set_status_code(400).unwrap();
let body = response.body().unwrap();

ResponseOutparam::set(outparam, Ok(response));

OutgoingBody::finish(body, None).unwrap();
return_response(outparam, 400, b"Bad Request");
return;
};

Expand All @@ -61,31 +55,17 @@ impl incoming_handler::Guest for Component {
.unwrap();
// Write the request body.
let outgoing_body = outgoing_request.body().unwrap();
{
let outgoing_stream = outgoing_body.write().unwrap();
let message = b"Hello, world!";
let mut offset = 0;
loop {
let write = outgoing_stream.check_write().unwrap();
if write == 0 {
outgoing_stream.subscribe().block();
} else {
let count = (write as usize).min(message.len() - offset);
outgoing_stream.write(&message[offset..][..count]).unwrap();
offset += count;
if offset == message.len() {
outgoing_stream.flush().unwrap();
break;
}
}
}
// The outgoing stream must be dropped before the outgoing body is finished.
}
OutgoingBody::finish(outgoing_body, None).unwrap();
write_outgoing_body(outgoing_request.body().unwrap(), b"Hello, world!");

// Get the incoming response.
let response = outgoing_handler::handle(outgoing_request, None).unwrap();
let response = match outgoing_handler::handle(outgoing_request, None) {
Ok(r) => r,
Err(e) => {
return_response(outparam, 500, e.to_string().as_bytes());
return;
}
};

let response = loop {
if let Some(response) = response.get() {
break response.unwrap().unwrap();
Expand Down Expand Up @@ -126,3 +106,34 @@ impl incoming_handler::Guest for Component {
OutgoingBody::finish(outgoing_body, None).unwrap();
}
}

fn write_outgoing_body(outgoing_body: OutgoingBody, message: &[u8]) {
{
let outgoing_stream = outgoing_body.write().unwrap();
let mut offset = 0;
loop {
let write = outgoing_stream.check_write().unwrap();
if write == 0 {
outgoing_stream.subscribe().block();
} else {
let count = (write as usize).min(message.len() - offset);
outgoing_stream.write(&message[offset..][..count]).unwrap();
offset += count;
if offset == message.len() {
outgoing_stream.flush().unwrap();
break;
}
}
}
// The outgoing stream must be dropped before the outgoing body is finished.
}
OutgoingBody::finish(outgoing_body, None).unwrap();
}

fn return_response(outparam: ResponseOutparam, status: u16, body: &[u8]) {
let response = OutgoingResponse::new(Headers::new());
response.set_status_code(status).unwrap();
write_outgoing_body(response.body().unwrap(), body);

ResponseOutparam::set(outparam, Ok(response));
}
2 changes: 1 addition & 1 deletion crates/conformance-tests/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl Request {
let port = env.get_port(value.parse().context("port must be a number")?)?;
match port {
Some(port) => Ok(Some(port.to_string())),
None => Ok(None),
None => anyhow::bail!("no port {value} exposed by any service"),
}
} else {
Ok(None)
Expand Down
9 changes: 6 additions & 3 deletions crates/conformance-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub fn tests(tests_dir: &Path) -> anyhow::Result<impl Iterator<Item = Test>> {
let config = r#try!(json5::from_str::<config::TestConfig>(&config)
.context("test config could not be parsed"));

let component_name = format!("{name}.wasm");
let component_name = "component.wasm";
Some(Ok(Test {
name,
config,
Expand Down Expand Up @@ -93,9 +93,12 @@ pub mod assertions {
) -> anyhow::Result<()> {
anyhow::ensure!(
actual.status() == expected.status,
"actual status {} != expected status {}",
"actual status {} != expected status {}\nbody:\n{}",
actual.status(),
expected.status
expected.status,
actual
.text()
.unwrap_or_else(|_| String::from("<invalid utf-8>"))
);

let mut actual_headers = actual
Expand Down
4 changes: 2 additions & 2 deletions crates/test-environment/src/manifest_template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ pub fn replace_template(
'outer: loop {
'inner: for captures in regex.captures_iter(content) {
let (Some(full), Some(capture)) = (captures.get(0), captures.get(1)) else {
continue;
continue 'inner;
};
let template = capture.as_str();
let (template_key, template_value) = template.split_once('=').with_context(|| {
Expand All @@ -107,7 +107,7 @@ pub fn replace_template(
if let Some(replacement) = replacement(template_key, template_value)? {
content.replace_range(full.range(), &replacement);
// Restart the search after a substitution
break 'inner;
continue 'outer;
}
}
// Break the outer loop if no substitutions were made
Expand Down
25 changes: 11 additions & 14 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ fn substitute_source(
static TEMPLATE_REGEX: OnceLock<regex::Regex> = OnceLock::new();
let regex = TEMPLATE_REGEX.get_or_init(|| regex::Regex::new(r"%\{(.*?)\}").unwrap());
'outer: loop {
'inner: for captures in regex.captures_iter(&manifest) {
for captures in regex.captures_iter(manifest) {
let (Some(full), Some(capture)) = (captures.get(0), captures.get(1)) else {
continue;
};
Expand All @@ -172,19 +172,16 @@ fn substitute_source(
format!("invalid template '{template}'(template should be in the form $KEY=$VALUE)")
})?;
let (template_key, template_value) = (template_key.trim(), template_value.trim());
match template_key {
"source" => {
let path = components
.get(template_value)
.with_context(|| format!("'{template_value}' is not a known component"))?;
let component_file = format!("{template_value}.wasm");
std::fs::copy(path, test_archive.join(&component_file))?;
println!("Substituting {template} with {component_file}...");
manifest.replace_range(full.range(), &component_file);
// Restart the search after a substitution
break 'inner;
}
_ => {}
if "source" == template_key {
let path = components
.get(template_value)
.with_context(|| format!("'{template_value}' is not a known component"))?;
let component_file = "component.wasm";
std::fs::copy(path, test_archive.join(component_file))?;
println!("Substituting {template} with {component_file}...");
manifest.replace_range(full.range(), component_file);
// Restart the search after a substitution
continue 'outer;
}
}
// Break the outer loop if no substitutions were made
Expand Down
13 changes: 13 additions & 0 deletions tests/outbound-wasi-http-v0.2.0-no-perms/spin.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
spin_manifest_version = 2

[application]
name = "wasi-http"
version = "0.1.0"
authors = ["Fermyon Engineering <engineering@fermyon.com>"]

[[trigger.http]]
route = "/"
component = "test"

[component.test]
source = "%{source=outbound-wasi-http-v0.2.0}"
30 changes: 30 additions & 0 deletions tests/outbound-wasi-http-v0.2.0-no-perms/test.json5
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"invocations": [
{
"request": {
"path": "/",
"headers": [
{
"name": "url",
"value": "http://localhost:%{port=80}"
}
]
},
"response": {
"status": 500,
"headers": [
{
"name": "transfer-encoding",
"value": "chunked"
},
{
"name": "Date",
"optional": true
}
],
"body": "ErrorCode::HttpRequestDenied"
},
}
],
"services": ["http-echo"]
}
12 changes: 0 additions & 12 deletions tests/outbound-wasi-http-v0.2.0/test.json5
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,6 @@
"request": {
"path": "/",
"headers": [
{
"name": "User-Agent",
"value": "my-agent"
},
{
"name": "Accept",
"value": "*/*"
},
{
"name": "Host",
"value": "example.com"
},
{
"name": "url",
"value": "http://localhost:%{port=80}"
Expand Down

0 comments on commit 5adb6a0

Please sign in to comment.