Skip to content

Commit

Permalink
Provide public API for passing in a listener address and post
Browse files Browse the repository at this point in the history
  • Loading branch information
milleniumbug committed Sep 5, 2019
1 parent 8932ef6 commit b48ee72
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 21 deletions.
2 changes: 1 addition & 1 deletion rust/pact_consumer/src/mock_server.rs
Expand Up @@ -86,7 +86,7 @@ impl ValidatingMockServer {
fn with_mode_and_future_consumer<F>(pact: Pact, mode: Mode, future_consumer: F) -> ValidatingMockServer
where F: FnOnce(Box<dyn futures::Future<Item = (), Error = ()> + 'static + Send>)
{
let (mock_server, future) = mock_server::MockServer::new("".into(), pact, 0)
let (mock_server, future) = mock_server::MockServer::new("".into(), pact, ([0, 0, 0, 0], 0 as u16).into())
.expect("error starting mock server");

future_consumer(Box::new(future));
Expand Down
5 changes: 2 additions & 3 deletions rust/pact_mock_server/src/hyper_server.rs
Expand Up @@ -210,12 +210,11 @@ fn handle_mock_request_error(result: Result<Response<Body>, InteractionError>) -

pub fn create_and_bind(
pact: Pact,
port: u16,
addr: std::net::SocketAddr,
shutdown: impl Future<Item = (), Error = ()>,
matches: Arc<Mutex<Vec<MatchResult>>>,
) -> Result<(impl Future<Item = (), Error = ()>, std::net::SocketAddr), hyper::Error> {
let pact = Arc::new(pact);
let addr = ([0, 0, 0, 0], port).into();

let server = Server::try_bind(&addr)?
.serve(move || {
Expand Down Expand Up @@ -251,7 +250,7 @@ mod tests {
let (shutdown_tx, shutdown_rx) = futures::sync::oneshot::channel();
let matches = Arc::new(Mutex::new(vec![]));

let (future, _) = create_and_bind(Pact::default(), 0, shutdown_rx.map_err(|_| ()), matches.clone()).unwrap();
let (future, _) = create_and_bind(Pact::default(), ([0, 0, 0, 0], 0 as u16).into(), shutdown_rx.map_err(|_| ()), matches.clone()).unwrap();

runtime.spawn(future);
shutdown_tx.send(()).unwrap();
Expand Down
36 changes: 25 additions & 11 deletions rust/pact_mock_server/src/lib.rs
Expand Up @@ -105,21 +105,21 @@ lazy_static! {
/// An error with a message will be returned in the following conditions:
///
/// - If a mock server is not able to be started
pub fn start_mock_server(id: String, pact: Pact, port: i32) -> Result<i32, String> {
pub fn start_mock_server(id: String, pact: Pact, addr: std::net::SocketAddr) -> Result<i32, String> {
MANAGER.lock().unwrap()
.get_or_insert_with(ServerManager::new)
.start_mock_server(id, pact, port as u16)
.map(|port| port as i32)
.start_mock_server_with_addr(id, pact, addr)
.map(|addr| addr.port() as i32)
}

/// Creates a mock server. Requires the pact JSON as a string as well as the port for the mock
/// server to run on. A value of 0 for the port will result in a
/// port being allocated by the operating system. The port of the mock server is returned.
pub extern fn create_mock_server(pact_json: &str, port: i32) -> Result<i32, MockServerError> {
pub extern fn create_mock_server(pact_json: &str, addr: std::net::SocketAddr) -> Result<i32, MockServerError> {
match serde_json::from_str(pact_json) {
Ok(pact_json) => {
let pact = Pact::from_json(&s!("<create_mock_server>"), &pact_json);
start_mock_server(Uuid::new_v4().simple().to_string(), pact, port)
start_mock_server(Uuid::new_v4().simple().to_string(), pact, addr)
.map_err(|err| {
error!("Could not start mock server: {}", err);
MockServerError::MockServerFailedToStart
Expand All @@ -146,9 +146,10 @@ pub extern fn create_mock_server(pact_json: &str, port: i32) -> Result<i32, Mock
/// | -2 | The pact JSON could not be parsed |
/// | -3 | The mock server could not be started |
/// | -4 | The method panicked |
/// | -5 | The address is not valid |
///
#[no_mangle]
pub extern fn create_mock_server_ffi(pact_str: *const c_char, port: i32) -> i32 {
pub extern fn create_mock_server_ffi(pact_str: *const c_char, addr_str: *const c_char) -> i32 {
env_logger::init().unwrap_or(());

let result = catch_unwind(|| {
Expand All @@ -160,13 +161,26 @@ pub extern fn create_mock_server_ffi(pact_str: *const c_char, port: i32) -> i32
CStr::from_ptr(pact_str)
};

match create_mock_server(str::from_utf8(c_str.to_bytes()).unwrap(), port) {
Ok(ms_port) => ms_port,
Err(err) => match err {
MockServerError::InvalidPactJson => -2,
MockServerError::MockServerFailedToStart => -3
let addr_c_str = unsafe {
if addr_str.is_null() {
error!("Got a null pointer instead of listener address");
return -1;
}
CStr::from_ptr(addr_str)
};

if let Ok(Ok(addr)) = str::from_utf8(addr_c_str.to_bytes()).map(|s| s.parse::<std::net::SocketAddr>()) {
match create_mock_server(str::from_utf8(c_str.to_bytes()).unwrap(), addr) {
Ok(ms_port) => ms_port,
Err(err) => match err {
MockServerError::InvalidPactJson => -2,
MockServerError::MockServerFailedToStart => -3
}
}
}
else {
-5
}
});

match result {
Expand Down
4 changes: 2 additions & 2 deletions rust/pact_mock_server/src/mock_server.rs
Expand Up @@ -37,13 +37,13 @@ pub struct MockServer {

impl MockServer {
/// Create a new mock server, consisting of its state (self) and its executable server future.
pub fn new(id: String, pact: Pact, port: u16) -> Result<(MockServer, impl Future<Item = (), Error = ()>), String> {
pub fn new(id: String, pact: Pact, addr: std::net::SocketAddr) -> Result<(MockServer, impl Future<Item = (), Error = ()>), String> {
let (shutdown_tx, shutdown_rx) = futures::sync::oneshot::channel();
let matches = Arc::new(Mutex::new(vec![]));

let (future, socket_addr) = hyper_server::create_and_bind(
pact.clone(),
port as u16,
addr,
shutdown_rx.map_err(|_| ()),
matches.clone()
).map_err(|err| format!("Could not start server: {}", err))?;
Expand Down
12 changes: 8 additions & 4 deletions rust/pact_mock_server/src/server_manager.rs
Expand Up @@ -27,14 +27,18 @@ impl ServerManager {
}

/// Start a new server on the runtime
pub fn start_mock_server(&mut self, id: String, pact: Pact, port: u16) -> Result<u16, String> {
let (mock_server, future) = MockServer::new(id.clone(), pact, port)?;
pub fn start_mock_server_with_addr(&mut self, id: String, pact: Pact, addr: std::net::SocketAddr) -> Result<std::net::SocketAddr, String> {
let (mock_server, future) = MockServer::new(id.clone(), pact, addr)?;
self.runtime.spawn(future);
let port = mock_server.addr.port();
let addr = mock_server.addr;

self.mock_servers.insert(id, Box::new(mock_server));
Ok(addr)
}

Ok(port)
/// Start a new server on the runtime
pub fn start_mock_server(&mut self, id: String, pact: Pact, port: u16) -> Result<u16, String> {
self.start_mock_server_with_addr(id, pact, ([0, 0, 0, 0], port as u16).into()).map(|addr| addr.port())
}

/// Shut down a server by its id
Expand Down

0 comments on commit b48ee72

Please sign in to comment.