diff --git a/fixture/client.html.tee.json b/fixture/client.html.tee.json new file mode 100644 index 000000000..29f9e0118 --- /dev/null +++ b/fixture/client.html.tee.json @@ -0,0 +1,84 @@ +{ + "mode": "TEE", + "notary_host": "localhost", + "notary_port": 7443, + "notary_ca_cert": "MIIFszCCA5ugAwIBAgIUeXLQmnjeXsHpGji7xA8oJjjw7WwwDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCVBhbG8gQWx0bzEVMBMGA1UECgwMT3JnYW5pemF0aW9uMRowGAYDVQQDDBFMb2NhbGhvc3QgUm9vdCBDQTAeFw0yNDA2MDcyMjUyNDBaFw0yOTA2MDYyMjUyNDBaMGkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlQYWxvIEFsdG8xFTATBgNVBAoMDE9yZ2FuaXphdGlvbjEaMBgGA1UEAwwRTG9jYWxob3N0IFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDIHMEL9gVSxT/J0qS4xDkDZs1d1UG0+z6NFLLsGdV7gu0ZJbDPlNd0kpjWsisVNB7TcqWoq5ROK5CR+6lZxXC8nbqr2YAJ2O8mHIXcYv7msAN3UYxtM6v1M7K+vNMJdDjZVAxcOKq5R7uUDUPw1weePz6eVEjntAW8mUjqkfnCqYml943Ud3724SkI5wyUT9rKS3bk6hvneq1ah/b1zRGDF2gp+T/oNe4ieS/LGoIUluE2csGRXtt542gpJnw5L54JASmGgt6hunUSWtoaht7Qxv6hYpieu4iHqZY1kfcFDjDH2WI16g1YqrWHzk1l7vWNLVDEcK3kdSQ1GmYAij8ZjAi0LJizLwtN//EkfxiOPlV435itK3uugY+etxrk77BeA6PmVcpZeLLXYuKSrzfaBh0ifP2p0uRlShURi5Rz4IE0I7wHkZ44x9MKYv8YzXK7O29HD158tgorxqwwKmkHqSxWpp7SRKvNnMulHN/el+IKDrPeBhVXsSSkd6U+/H61q7i0SY9TqqhdiMQLW/efK9LkVRen5myhwqogwiF/42Jp2nrCeuzv5YDsAFSrQ0lukW+Hz7FXV+0axnKeXZ08Nd+IS1BhGyMgHo6PWMP1fWyfO0DJVUfIqrHqvBy8bW0yNOuhiyU2oeyDRKv75OMxpIrUeX3qvmrVcYUPvfXsVQIDAQABo1MwUTAdBgNVHQ4EFgQUlro6UuKRY+lHZ3T4FQMhoQAJ2a8wHwYDVR0jBBgwFoAUlro6UuKRY+lHZ3T4FQMhoQAJ2a8wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEARliSCLdjNI5fFkNwXDK6k6jN5hITrY07XIawUIEwinjQqgLkYFvzXbMtfLwsWmxMPjDVYYDa5Y2NAGcH08b//2z9EuHxMOTOFTKr59BEcVxV1cxV+lspAunH8DLSlLJhf/EeR+MhIIHAfhlE8V7lvlE1EbM+Uj5JYIeefV/4omsGrphyHD3oSJAQDae0su200I/i2yAaTrwXLZ4HtaXsnxKZ4PMPFWaLvMQ8DsLgx2VB3/vQJn74Xepau6mYEWlRnUu90mj79gJOnwBKPlLojF6dJOMIJ2YHr9fI8sUfkVwPFVlkDKJcr0ll5RL3O/naNlLQZuOgijOM5YF5iTrefliVodEHpBPID2mhtq/E+ZIQWLpik8ulsJ8ufN9YfrbjbsiC/KeoMqoFCImRSyMGQDMADo4EV3DNfDFvfrHx0qBMmJ0nkhuGobphegMPCjZ3axvQwQulKuHXmFpAvGYcpK/twBMC1MJkV04tIwVEDZG6id5oKYtrIXHdSFshf6r3z4bbgq6kJnOxZ8Vo4cEw/dgc3hRivr+HnxOJcEk2CTQlCVOiCQAg64OqDEOoswVg6nzoO3RJhFatu+abO22MIXPNGma02zBoQZLYpGzL9z6pMnPKjL15G9H1SYVSTGhmq+GVtdRibg8rLBciSm3ERd7gNRqvYP5GrjCtUIbOTEc=", + "target_method": "GET", + "target_url": "https://en.wikipedia.org/wiki/Claude_Shannon", + "target_headers": {}, + "target_body": "", + "max_sent_data": 10000, + "max_recv_data": 10000, + "manifest": { + "manifestVersion": "1", + "id": "wikipedia-claude-shannon", + "title": "Wikipedia Claude Shannon", + "description": "Generate a proof that you have visited the Claude Shannon Wikipedia page", + "prepareUrl": "https://en.wikipedia.org/wiki/Claude_Shannon", + "request": { + "method": "GET", + "version": "HTTP/1.1", + "url": "https://en.wikipedia.org/wiki/Claude_Shannon", + "headers": {} + }, + "response": { + "status": "200", + "version": "HTTP/1.1", + "message": "OK", + "headers": { + "Content-Type": "text/html; charset=UTF-8" + }, + "body": { + "format": "html", + "extractors": [ + { + "id": "pageTitle", + "description": "Extract the page title", + "selector": [ + "title" + ], + "type": "string", + "predicates": [ + { + "type": "value", + "comparison": "contains", + "value": "Claude Shannon" + } + ] + }, + { + "id": "roles", + "description": "Extract his professional roles", + "selector": [ + "div#mw-content-text", + "div.mw-parser-output", + "p", + "a" + ], + "type": "array", + "predicates": [ + { + "type": "value", + "comparison": "contains", + "value": "mathematician", + "case_sensitive": false + }, + { + "type": "value", + "comparison": "contains", + "value": "electrical engineer", + "case_sensitive": false + }, + { + "type": "value", + "comparison": "contains", + "value": "cryptographer", + "case_sensitive": false + } + ] + } + ] + } + } + } +} \ No newline at end of file diff --git a/fixture/client.html.tee_tcp_local.json b/fixture/client.html.tee_tcp_local.json deleted file mode 100644 index 41555a9da..000000000 --- a/fixture/client.html.tee_tcp_local.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "mode": "TEE", - "notary_host": "localhost", - "notary_port": 7443, - "notary_ca_cert": "MIIFszCCA5ugAwIBAgIUeXLQmnjeXsHpGji7xA8oJjjw7WwwDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCVBhbG8gQWx0bzEVMBMGA1UECgwMT3JnYW5pemF0aW9uMRowGAYDVQQDDBFMb2NhbGhvc3QgUm9vdCBDQTAeFw0yNDA2MDcyMjUyNDBaFw0yOTA2MDYyMjUyNDBaMGkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlQYWxvIEFsdG8xFTATBgNVBAoMDE9yZ2FuaXphdGlvbjEaMBgGA1UEAwwRTG9jYWxob3N0IFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDIHMEL9gVSxT/J0qS4xDkDZs1d1UG0+z6NFLLsGdV7gu0ZJbDPlNd0kpjWsisVNB7TcqWoq5ROK5CR+6lZxXC8nbqr2YAJ2O8mHIXcYv7msAN3UYxtM6v1M7K+vNMJdDjZVAxcOKq5R7uUDUPw1weePz6eVEjntAW8mUjqkfnCqYml943Ud3724SkI5wyUT9rKS3bk6hvneq1ah/b1zRGDF2gp+T/oNe4ieS/LGoIUluE2csGRXtt542gpJnw5L54JASmGgt6hunUSWtoaht7Qxv6hYpieu4iHqZY1kfcFDjDH2WI16g1YqrWHzk1l7vWNLVDEcK3kdSQ1GmYAij8ZjAi0LJizLwtN//EkfxiOPlV435itK3uugY+etxrk77BeA6PmVcpZeLLXYuKSrzfaBh0ifP2p0uRlShURi5Rz4IE0I7wHkZ44x9MKYv8YzXK7O29HD158tgorxqwwKmkHqSxWpp7SRKvNnMulHN/el+IKDrPeBhVXsSSkd6U+/H61q7i0SY9TqqhdiMQLW/efK9LkVRen5myhwqogwiF/42Jp2nrCeuzv5YDsAFSrQ0lukW+Hz7FXV+0axnKeXZ08Nd+IS1BhGyMgHo6PWMP1fWyfO0DJVUfIqrHqvBy8bW0yNOuhiyU2oeyDRKv75OMxpIrUeX3qvmrVcYUPvfXsVQIDAQABo1MwUTAdBgNVHQ4EFgQUlro6UuKRY+lHZ3T4FQMhoQAJ2a8wHwYDVR0jBBgwFoAUlro6UuKRY+lHZ3T4FQMhoQAJ2a8wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEARliSCLdjNI5fFkNwXDK6k6jN5hITrY07XIawUIEwinjQqgLkYFvzXbMtfLwsWmxMPjDVYYDa5Y2NAGcH08b//2z9EuHxMOTOFTKr59BEcVxV1cxV+lspAunH8DLSlLJhf/EeR+MhIIHAfhlE8V7lvlE1EbM+Uj5JYIeefV/4omsGrphyHD3oSJAQDae0su200I/i2yAaTrwXLZ4HtaXsnxKZ4PMPFWaLvMQ8DsLgx2VB3/vQJn74Xepau6mYEWlRnUu90mj79gJOnwBKPlLojF6dJOMIJ2YHr9fI8sUfkVwPFVlkDKJcr0ll5RL3O/naNlLQZuOgijOM5YF5iTrefliVodEHpBPID2mhtq/E+ZIQWLpik8ulsJ8ufN9YfrbjbsiC/KeoMqoFCImRSyMGQDMADo4EV3DNfDFvfrHx0qBMmJ0nkhuGobphegMPCjZ3axvQwQulKuHXmFpAvGYcpK/twBMC1MJkV04tIwVEDZG6id5oKYtrIXHdSFshf6r3z4bbgq6kJnOxZ8Vo4cEw/dgc3hRivr+HnxOJcEk2CTQlCVOiCQAg64OqDEOoswVg6nzoO3RJhFatu+abO22MIXPNGma02zBoQZLYpGzL9z6pMnPKjL15G9H1SYVSTGhmq+GVtdRibg8rLBciSm3ERd7gNRqvYP5GrjCtUIbOTEc=", - "target_method": "GET", - "target_url": "https://en.wikipedia.org/wiki/Claude_Shannon", - "target_headers": {}, - "target_body": "", - "max_sent_data": 10000, - "max_recv_data": 10000, - "proving": { - "manifest": { - "manifestVersion": "2", - "id": "wikipedia-claude-shannon", - "title": "Wikipedia Claude Shannon", - "description": "Generate a proof that you have visited the Claude Shannon Wikipedia page", - "prepareUrl": "https://en.wikipedia.org/wiki/Claude_Shannon", - "request": { - "method": "GET", - "version": "HTTP/1.1", - "url": "https://en.wikipedia.org/wiki/Claude_Shannon", - "headers": { - "accept-encoding": "identity", - "host": "en.wikipedia.org", - "connection": "close", - "accept": "*/*", - "authorization": "Bearer <% accessToken %>" - }, - "vars": { - "accessToken": { - "description": "Spotify access token", - "required": true, - "pattern": "^[A-Za-z0-9_-]+$" - } - } - }, - "response": { - "status": "200", - "version": "HTTP/1.1", - "message": "OK", - "headers": { - "Content-Type": "text/html; charset=UTF-8" - }, - "body": { - "format": "html", - "extractors": [ - { - "id": "pageTitle", - "description": "Extract the page title", - "selector": ["title"], - "type": "string", - "predicates": [ - { - "type": "value", - "comparison": "contains", - "value": "Claude Shannon" - } - ] - }, - { - "id": "roles", - "description": "Extract his professional roles", - "selector": ["div#mw-content-text", "div.mw-parser-output", "p", "a"], - "type": "array", - "predicates": [ - { - "type": "value", - "comparison": "contains", - "value": "mathematician", - "case_sensitive": false - }, - { - "type": "value", - "comparison": "contains", - "value": "electrical engineer", - "case_sensitive": false - }, - { - "type": "value", - "comparison": "contains", - "value": "cryptographer", - "case_sensitive": false - } - ] - } - ] - } - } - } - } -} \ No newline at end of file diff --git a/fixture/client.proxy.json b/fixture/client.json.proxy.json similarity index 54% rename from fixture/client.proxy.json rename to fixture/client.json.proxy.json index 4b387f458..b5803d462 100644 --- a/fixture/client.proxy.json +++ b/fixture/client.json.proxy.json @@ -3,62 +3,40 @@ "notary_port": 7443, "notary_ca_cert": "MIIFszCCA5ugAwIBAgIUeXLQmnjeXsHpGji7xA8oJjjw7WwwDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCVBhbG8gQWx0bzEVMBMGA1UECgwMT3JnYW5pemF0aW9uMRowGAYDVQQDDBFMb2NhbGhvc3QgUm9vdCBDQTAeFw0yNDA2MDcyMjUyNDBaFw0yOTA2MDYyMjUyNDBaMGkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlQYWxvIEFsdG8xFTATBgNVBAoMDE9yZ2FuaXphdGlvbjEaMBgGA1UEAwwRTG9jYWxob3N0IFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDIHMEL9gVSxT/J0qS4xDkDZs1d1UG0+z6NFLLsGdV7gu0ZJbDPlNd0kpjWsisVNB7TcqWoq5ROK5CR+6lZxXC8nbqr2YAJ2O8mHIXcYv7msAN3UYxtM6v1M7K+vNMJdDjZVAxcOKq5R7uUDUPw1weePz6eVEjntAW8mUjqkfnCqYml943Ud3724SkI5wyUT9rKS3bk6hvneq1ah/b1zRGDF2gp+T/oNe4ieS/LGoIUluE2csGRXtt542gpJnw5L54JASmGgt6hunUSWtoaht7Qxv6hYpieu4iHqZY1kfcFDjDH2WI16g1YqrWHzk1l7vWNLVDEcK3kdSQ1GmYAij8ZjAi0LJizLwtN//EkfxiOPlV435itK3uugY+etxrk77BeA6PmVcpZeLLXYuKSrzfaBh0ifP2p0uRlShURi5Rz4IE0I7wHkZ44x9MKYv8YzXK7O29HD158tgorxqwwKmkHqSxWpp7SRKvNnMulHN/el+IKDrPeBhVXsSSkd6U+/H61q7i0SY9TqqhdiMQLW/efK9LkVRen5myhwqogwiF/42Jp2nrCeuzv5YDsAFSrQ0lukW+Hz7FXV+0axnKeXZ08Nd+IS1BhGyMgHo6PWMP1fWyfO0DJVUfIqrHqvBy8bW0yNOuhiyU2oeyDRKv75OMxpIrUeX3qvmrVcYUPvfXsVQIDAQABo1MwUTAdBgNVHQ4EFgQUlro6UuKRY+lHZ3T4FQMhoQAJ2a8wHwYDVR0jBBgwFoAUlro6UuKRY+lHZ3T4FQMhoQAJ2a8wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEARliSCLdjNI5fFkNwXDK6k6jN5hITrY07XIawUIEwinjQqgLkYFvzXbMtfLwsWmxMPjDVYYDa5Y2NAGcH08b//2z9EuHxMOTOFTKr59BEcVxV1cxV+lspAunH8DLSlLJhf/EeR+MhIIHAfhlE8V7lvlE1EbM+Uj5JYIeefV/4omsGrphyHD3oSJAQDae0su200I/i2yAaTrwXLZ4HtaXsnxKZ4PMPFWaLvMQ8DsLgx2VB3/vQJn74Xepau6mYEWlRnUu90mj79gJOnwBKPlLojF6dJOMIJ2YHr9fI8sUfkVwPFVlkDKJcr0ll5RL3O/naNlLQZuOgijOM5YF5iTrefliVodEHpBPID2mhtq/E+ZIQWLpik8ulsJ8ufN9YfrbjbsiC/KeoMqoFCImRSyMGQDMADo4EV3DNfDFvfrHx0qBMmJ0nkhuGobphegMPCjZ3axvQwQulKuHXmFpAvGYcpK/twBMC1MJkV04tIwVEDZG6id5oKYtrIXHdSFshf6r3z4bbgq6kJnOxZ8Vo4cEw/dgc3hRivr+HnxOJcEk2CTQlCVOiCQAg64OqDEOoswVg6nzoO3RJhFatu+abO22MIXPNGma02zBoQZLYpGzL9z6pMnPKjL15G9H1SYVSTGhmq+GVtdRibg8rLBciSm3ERd7gNRqvYP5GrjCtUIbOTEc=", "target_body": "", - "proving": { - "manifest": { - "manifestVersion": "1", - "id": "reddit-user-karma", - "title": "Total Reddit Karma", - "description": "Generate a proof that you have a certain amount of karma", - "prepareUrl": "https://www.reddit.com/login/", - "request": { - "method": "GET", - "version": "HTTP/1.1", - "url": "https://gist.githubusercontent.com/mattes/23e64faadb5fd4b5112f379903d2572e/raw/74e517a60c21a5c11d94fec8b572f68addfade39/example.json", - "headers": { - }, - "body": { - "userId": "<% userId %>" - }, - "vars": { - "userId": { - "description": "Reddit username", - "required": true, - "pattern": "^[A-Za-z0-9_-]{3,20}$" - }, - "authToken": { - "description": "Authentication token", - "required": false, - "default": "abcdef1234567890abcdef1234567890", - "pattern": "^[A-Za-z0-9]{32}$" - } - }, - "extra": { - "headers": { - "User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36", - "Content-Type": "application/json" - } - } + "target_method": "GET", + "target_url": "https://gist.githubusercontent.com/mattes/23e64faadb5fd4b5112f379903d2572e/raw/74e517a60c21a5c11d94fec8b572f68addfade39/example.json", + "target_headers": {}, + "manifest": { + "manifestVersion": "1", + "id": "hello-world", + "title": "Hello World example", + "description": "Prove that a gist contains a hello world message", + "prepareUrl": "https://gist.githubusercontent.com/mattes/23e64faadb5fd4b5112f379903d2572e/raw/74e517a60c21a5c11d94fec8b572f68addfade39/example.json", + "request": { + "method": "GET", + "version": "HTTP/1.1", + "url": "https://gist.githubusercontent.com/mattes/23e64faadb5fd4b5112f379903d2572e/raw/74e517a60c21a5c11d94fec8b572f68addfade39/example.json", + "headers": {} + }, + "response": { + "status": "200", + "version": "HTTP/1.1", + "message": "OK", + "headers": { + "Content-Type": "text/plain; charset=utf-8" }, - "response": { - "status": "200", - "version": "HTTP/1.1", - "message": "OK", - "headers": { - "Content-Type": "text/plain; charset=utf-8" - }, - "body": { - "format": "json", - "extractors": [ - { - "id": "helloValue", - "description": "Extract the hello value", - "selector": [ - "hello" - ], - "type": "string" - } - ] - } + "body": { + "format": "json", + "extractors": [ + { + "id": "helloValue", + "description": "Extract the hello value", + "selector": [ + "hello" + ], + "type": "string" + } + ] } } } diff --git a/notary/src/proxy.rs b/notary/src/proxy.rs index 3f24c2847..76a0c8a98 100644 --- a/notary/src/proxy.rs +++ b/notary/src/proxy.rs @@ -7,7 +7,7 @@ use axum::{ use reqwest::{Request, Response}; use serde::Deserialize; use serde_json::Value; -use tracing::info; +use tracing::{debug, info}; use uuid::Uuid; use web_prover_core::{ hash::keccak_digest, @@ -19,10 +19,11 @@ use web_prover_core::{ }; use crate::{ - error::NotaryServerError, + error::{NotaryServerError, ProxyError}, verifier::{sign_verification, VerifyOutput}, SharedState, }; + #[derive(Deserialize)] pub struct NotarizeQuery { session_id: Uuid, @@ -54,7 +55,7 @@ pub async fn proxy( let request = from_reqwest_request(&reqwest_request); // debug!("{:?}", request); - let response = from_reqwest_response(reqwest_response).await; + let response = from_reqwest_response(reqwest_response).await?; // debug!("{:?}", response); let tee_proof = create_tee_proof(&payload.manifest, &request, &response, State(state))?; @@ -64,7 +65,7 @@ pub async fn proxy( // TODO: This, similarly to other from_* methods, should be a trait // Requires adding reqwest to proofs crate -async fn from_reqwest_response(response: Response) -> NotaryResponse { +async fn from_reqwest_response(response: Response) -> Result { let status = response.status().as_u16().to_string(); let version = format!("{:?}", response.version()); let message = response.status().canonical_reason().unwrap_or("").to_string(); @@ -73,8 +74,17 @@ async fn from_reqwest_response(response: Response) -> NotaryResponse { .iter() .map(|(k, v)| (capitalize_header(k.as_ref()), v.to_str().unwrap_or("").to_string())) .collect(); - let json = response.json().await.ok(); - NotaryResponse { + let body = response + .bytes() + .await + .map_err(|_| { + NotaryServerError::ProxyError(ProxyError::Io(std::io::Error::new( + std::io::ErrorKind::Other, + "Failed to read response body", + ))) + })? + .to_vec(); + Ok(NotaryResponse { response: ManifestResponse { status, version, @@ -83,8 +93,9 @@ async fn from_reqwest_response(response: Response) -> NotaryResponse { // TODO: This makes me think that perhaps this should be an optional field or something else body: ManifestResponseBody::default(), }, - notary_response_body: NotaryResponseBody { body: json }, - } + // TODO: Should we remove Option<_> on body? + notary_response_body: NotaryResponseBody { body: Some(body) }, + }) } fn from_reqwest_request(request: &Request) -> ManifestRequest { @@ -142,6 +153,7 @@ fn validate_notarization_legal( request: &ManifestRequest, response: &NotaryResponse, ) -> Result { + debug!("Validating manifest"); let result = manifest.validate_with(request, response)?; if !result.is_success() { info!("Manifest validation failed: {:?}", result.errors()); diff --git a/tests/src/lib.rs b/tests/src/lib.rs index 6af5fced7..43b10d845 100644 --- a/tests/src/lib.rs +++ b/tests/src/lib.rs @@ -12,13 +12,33 @@ use std::{ use tokio::time::{sleep, timeout}; +// File paths +const NOTARY_CONFIG_PATH: &str = "fixture/notary-config.toml"; +const CLIENT_CONFIG_PATHS: [&str; 2] = + ["fixture/client.json.proxy.json", "fixture/client.html.tee.json"]; +const RELEASE_DIR: &str = "target/release"; + +// Binary names +const NOTARY_BIN: &str = "web-prover-notary"; +const CLIENT_BIN: &str = "web-prover-client"; + +// Timeouts and delays +const NOTARY_READY_TIMEOUT: Duration = Duration::from_secs(60); +const PROVING_TIMEOUT: Duration = Duration::from_secs(60); +const NOTARY_STARTUP_DELAY: Duration = Duration::from_secs(5); +const POLL_INTERVAL: Duration = Duration::from_millis(100); + +// Log messages +const NOTARY_READY_MSG: &str = "Listening on https://0.0.0.0:7443"; +const PROVING_SUCCESS_MSG: &str = "Proving Successful"; + struct TestSetup { notary: Child, client: Child, } impl TestSetup { - async fn new() -> Self { + async fn new(client_config_path: &str) -> Self { // Find the workspace root directory let workspace_root = { let output = @@ -37,14 +57,14 @@ impl TestSetup { println!("Workspace root: {:?}", workspace_root); // Check for pre-built binaries in target/release - let notary_bin = workspace_root.join("target/release/notary"); - let client_bin = workspace_root.join("target/release/client"); + let notary_bin = workspace_root.join(RELEASE_DIR).join(NOTARY_BIN); + let client_bin = workspace_root.join(RELEASE_DIR).join(CLIENT_BIN); let use_prebuilt = notary_bin.exists() && client_bin.exists(); println!("Using pre-built binaries: {}", use_prebuilt); // Print the config file content for debugging - let notary_config_path = workspace_root.join("fixture/notary-config.toml"); + let notary_config_path = workspace_root.join(NOTARY_CONFIG_PATH); if notary_config_path.exists() { match std::fs::read_to_string(¬ary_config_path) { Ok(content) => println!("Notary config content:\n{}", content), @@ -54,15 +74,14 @@ impl TestSetup { println!("Notary config file not found at {:?}", notary_config_path); } - // This matches exactly what worked in your shell script + // Start notary let mut notary = if use_prebuilt { - // Change directory to workspace root first std::env::set_current_dir(&workspace_root).unwrap(); println!("Current directory: {:?}", std::env::current_dir().unwrap()); - let cmd = Command::new("./target/release/notary") + let cmd = Command::new(format!("./{}/{}", RELEASE_DIR, NOTARY_BIN)) .arg("--config") - .arg("./fixture/notary-config.toml") + .arg(format!("./{}", NOTARY_CONFIG_PATH)) .env("RUST_LOG", "DEBUG") .stdout(Stdio::piped()) .stderr(Stdio::piped()) @@ -73,7 +92,7 @@ impl TestSetup { cmd } else { Command::new("cargo") - .args(["run", "-p", "notary", "--release", "--"]) + .args(["run", "-p", NOTARY_BIN, "--release", "--"]) .arg("--config") .arg(notary_config_path) .env("RUST_LOG", "DEBUG") @@ -100,7 +119,7 @@ impl TestSetup { for line in stdout_reader.lines().chain(stderr_reader.lines()) { if let Ok(line) = line { println!("Notary: {}", line); - if line.contains("Listening on https://0.0.0.0:7443") { + if line.contains(NOTARY_READY_MSG) { ready_flag_clone.store(true, Ordering::SeqCst); break; } @@ -109,13 +128,11 @@ impl TestSetup { }); // Wait for notary to be ready with a timeout, or sleep 10 seconds like the original workflow - match timeout(Duration::from_secs(60), async { + match timeout(NOTARY_READY_TIMEOUT, async { while !ready_flag.load(Ordering::SeqCst) { - sleep(Duration::from_millis(100)).await; + sleep(POLL_INTERVAL).await; } - - // Add extra delay to match original workflow - sleep(Duration::from_secs(5)).await; + sleep(NOTARY_STARTUP_DELAY).await; }) .await { @@ -126,14 +143,13 @@ impl TestSetup { }, } - // Start client with exact same pattern as the working workflow + // Start client let client = if use_prebuilt { - // We're already in workspace_root directory println!("Current directory before client: {:?}", std::env::current_dir().unwrap()); - let cmd = Command::new("./target/release/client") + let cmd = Command::new(format!("./{}/{}", RELEASE_DIR, CLIENT_BIN)) .arg("--config") - .arg("./fixture/client.proxy.json") + .arg(format!("./{}", client_config_path)) .env("RUST_LOG", "DEBUG") .stdout(Stdio::piped()) .stderr(Stdio::piped()) @@ -144,9 +160,9 @@ impl TestSetup { cmd } else { Command::new("cargo") - .args(["run", "-p", "client", "--"]) + .args(["run", "-p", CLIENT_BIN, "--"]) .arg("--config") - .arg(workspace_root.join("fixture/client.proxy.json")) + .arg(workspace_root.join(client_config_path)) .env("RUST_LOG", "DEBUG") .current_dir(&workspace_root) .stdout(Stdio::piped()) @@ -168,40 +184,45 @@ impl Drop for TestSetup { #[tokio::test] async fn test_proving_successful() { - let mut setup = TestSetup::new().await; - - let stdout = BufReader::new(setup.client.stdout.take().unwrap()); - let stderr = BufReader::new(setup.client.stderr.take().unwrap()); - - // Wait for proving successful with timeout - let result = timeout(Duration::from_secs(60), async { - let mut stdout_lines = stdout.lines(); - let mut stderr_lines = stderr.lines(); - loop { - // Check stdout - if let Some(Ok(line)) = stdout_lines.next() { - println!("Client stdout: {}", line); - if line.contains("Proving Successful") { - return true; + // Test each config path + for config_path in CLIENT_CONFIG_PATHS.into_iter() { + println!("Testing with config: {}", config_path); + + let mut setup = TestSetup::new(config_path).await; + + let stdout = BufReader::new(setup.client.stdout.take().unwrap()); + let stderr = BufReader::new(setup.client.stderr.take().unwrap()); + + let result = timeout(PROVING_TIMEOUT, async { + let mut stdout_lines = stdout.lines(); + let mut stderr_lines = stderr.lines(); + loop { + if let Some(Ok(line)) = stdout_lines.next() { + println!("Client stdout: {}", line); + if line.contains(PROVING_SUCCESS_MSG) { + return true; + } } - } - // Check stderr - if let Some(Ok(line)) = stderr_lines.next() { - println!("Client stderr: {}", line); - if line.contains("Proving Successful") { - return true; + if let Some(Ok(line)) = stderr_lines.next() { + println!("Client stderr: {}", line); + if line.contains(PROVING_SUCCESS_MSG) { + return true; + } } - } - // Small sleep to avoid busy waiting - sleep(Duration::from_millis(10)).await; + sleep(POLL_INTERVAL).await; + } + }) + .await; + + match result { + Ok(found) => assert!(found, "Did not find '{}' in output", PROVING_SUCCESS_MSG), + Err(_) => panic!( + "Timed out waiting for '{}' after {} seconds", + PROVING_SUCCESS_MSG, + PROVING_TIMEOUT.as_secs() + ), } - }) - .await; - - match result { - Ok(found) => assert!(found, "Did not find 'Proving Successful' in output"), - Err(_) => panic!("Timed out waiting for 'Proving Successful' after 60 seconds"), } }