Skip to content

Commit

Permalink
Add test-common library to consolidate testing code (#149)
Browse files Browse the repository at this point in the history
Add `test-common` library to consolidate testing code. Many tests were using duplicate code, in particular for mocks and fixtures. This PR adds a new library that helps consolidate these items.

Fixes #147
  • Loading branch information
wilyle authored Feb 28, 2024
1 parent d92cf05 commit a8b7816
Show file tree
Hide file tree
Showing 23 changed files with 389 additions and 397 deletions.
31 changes: 23 additions & 8 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ members = [
"proc_macros",
"proto/cloud_connector",
"proto/mapping_service",
"test_common",
]

[workspace.dependencies]
Expand All @@ -34,6 +35,7 @@ cloud-connector-proto = { path = "proto/cloud_connector" }
file-service-discovery-adapter = { path = "adapters/service_discovery/file_service_discovery_adapter" }
freyja-build-common = { path = "build_common" }
freyja-common = { path = "common" }
freyja-test-common = { path = "test_common" }
grpc-cloud-adapter = { path = "adapters/cloud/grpc_cloud_adapter" }
grpc-digital-twin-adapter = { path = "adapters/digital_twin/grpc_digital_twin_adapter" }
grpc-mapping-adapter = { path = "adapters/mapping/grpc_mapping_adapter" }
Expand Down
4 changes: 2 additions & 2 deletions adapters/cloud/grpc_cloud_adapter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ tonic = { workspace = true }
freyja-build-common = { workspace = true }

[dev-dependencies]
freyja-test-common = { workspace = true }
time = { workspace = true }
tokio-stream = { workspace = true }
tower = { workspace = true }
uuid = { workspace = true, features = ["v4"] }
tower = { workspace = true }
64 changes: 10 additions & 54 deletions adapters/cloud/grpc_cloud_adapter/src/grpc_cloud_adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,67 +123,20 @@ mod grpc_cloud_adapter_tests {
mod unix_tests {
use super::*;

use std::{
io::{stderr, Write},
path::PathBuf,
};
use std::path::PathBuf;

use tokio::net::{UnixListener, UnixStream};
use tokio_stream::wrappers::UnixListenerStream;
use tonic::{
transport::{Channel, Endpoint, Server, Uri},
Request, Response, Status,
Response,
};
use tower::service_fn;
use uuid::Uuid;

use cloud_connector_proto::v1::{
cloud_connector_server::{CloudConnector, CloudConnectorServer},
UpdateDigitalTwinRequest, UpdateDigitalTwinResponse,
cloud_connector_server::CloudConnectorServer, UpdateDigitalTwinResponse,
};

pub struct TestFixture {
pub socket_path: PathBuf,
}

impl TestFixture {
fn new() -> Self {
Self {
socket_path: std::env::temp_dir()
.as_path()
.join(Uuid::new_v4().as_hyphenated().to_string()),
}
}
}

impl Drop for TestFixture {
fn drop(&mut self) {
match std::fs::remove_file(&self.socket_path) {
Ok(_) => {}
Err(e) => {
write!(stderr(), "Error cleaning up `TestFixture`: {e:?}")
.expect("Error writing to stderr");
}
}
}
}

pub struct MockCloudConnector {}

#[tonic::async_trait]
impl CloudConnector for MockCloudConnector {
/// Updates a digital twin instance
///
/// # Arguments
/// - `request`: the request to send
async fn update_digital_twin(
&self,
_request: Request<UpdateDigitalTwinRequest>,
) -> Result<Response<UpdateDigitalTwinResponse>, Status> {
let response = UpdateDigitalTwinResponse {};
Ok(Response::new(response))
}
}
use freyja_test_common::{fixtures::GRPCTestFixture, mocks::MockCloudConnector};

async fn create_test_grpc_client(socket_path: PathBuf) -> CloudConnectorClient<Channel> {
let channel = Endpoint::try_from("http://URI_IGNORED") // Devskim: ignore DS137138
Expand All @@ -199,17 +152,20 @@ mod grpc_cloud_adapter_tests {
}

async fn run_test_grpc_server(uds_stream: UnixListenerStream) {
let mock_azure_connector = MockCloudConnector {};
let mut mock_cloud_connector = MockCloudConnector::new();
mock_cloud_connector
.expect_update_digital_twin()
.returning(|_| Ok(Response::new(UpdateDigitalTwinResponse::default())));
Server::builder()
.add_service(CloudConnectorServer::new(mock_azure_connector))
.add_service(CloudConnectorServer::new(mock_cloud_connector))
.serve_with_incoming(uds_stream)
.await
.unwrap();
}

#[tokio::test]
async fn send_request_to_provider() {
let fixture = TestFixture::new();
let fixture = GRPCTestFixture::new();

// Create the Unix Socket
let uds = UnixListener::bind(&fixture.socket_path).unwrap();
Expand Down
4 changes: 2 additions & 2 deletions adapters/cloud/in_memory_mock_cloud_adapter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ serde_json = { workspace = true }
tokio = { workspace = true }

[dev-dependencies]
time = { workspace = true }
mockall = { workspace = true }
freyja-test-common = { workspace = true }
time = { workspace = true }
Original file line number Diff line number Diff line change
Expand Up @@ -50,39 +50,25 @@ impl CloudAdapter for InMemoryMockCloudAdapter {
#[cfg(test)]
mod in_memory_mock_cloud_adapter_tests {
use super::*;
use mockall::*;

use std::collections::HashMap;

use time::OffsetDateTime;

use freyja_common::service_discovery_adapter::{
ServiceDiscoveryAdapter, ServiceDiscoveryAdapterError,
};

mock! {
pub ServiceDiscoveryAdapterSelectorImpl {}

#[async_trait]
impl ServiceDiscoveryAdapterSelector for ServiceDiscoveryAdapterSelectorImpl {
fn register(&mut self, adapter: Box<dyn ServiceDiscoveryAdapter + Send + Sync>) -> Result<(), ServiceDiscoveryAdapterError>;

async fn get_service_uri<'a>(&self, id: &'a str) -> Result<String, ServiceDiscoveryAdapterError>;
}
}
use freyja_test_common::mocks::MockServiceDiscoveryAdapterSelector;

#[test]
fn can_get_new() {
let result = InMemoryMockCloudAdapter::create_new(Arc::new(Mutex::new(
MockServiceDiscoveryAdapterSelectorImpl::new(),
MockServiceDiscoveryAdapterSelector::new(),
)));
assert!(result.is_ok());
}

#[tokio::test]
async fn can_send_to_cloud() {
let cloud_adapter = InMemoryMockCloudAdapter::create_new(Arc::new(Mutex::new(
MockServiceDiscoveryAdapterSelectorImpl::new(),
MockServiceDiscoveryAdapterSelector::new(),
)))
.unwrap();

Expand Down
2 changes: 1 addition & 1 deletion adapters/data/sample_grpc_data_adapter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ tokio = { workspace = true }
tonic = { workspace = true }

[dev-dependencies]
freyja-test-common = { workspace = true }
tokio-stream = { workspace = true }
tower = { workspace = true }
uuid = { workspace = true, features = ["v4"] }

[build-dependencies]
freyja-build-common = { workspace = true }
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ impl DataAdapter for SampleGRPCDataAdapter {
}

#[cfg(test)]
mod grpc_data_adapter_tests {
mod sample_grpc_data_adapter_tests {
use std::pin::Pin;

use super::*;
Expand Down Expand Up @@ -268,43 +268,14 @@ mod grpc_data_adapter_tests {

use super::*;

use std::{
io::{stderr, Write},
path::PathBuf,
sync::Arc,
};
use std::{path::PathBuf, sync::Arc};

use tokio::net::{UnixListener, UnixStream};
use tokio_stream::wrappers::UnixListenerStream;
use tonic::transport::{Channel, Endpoint, Server, Uri};
use tower::service_fn;
use uuid::Uuid;

pub struct TestFixture {
pub socket_path: PathBuf,
}

impl TestFixture {
fn new() -> Self {
Self {
socket_path: std::env::temp_dir()
.as_path()
.join(Uuid::new_v4().as_hyphenated().to_string()),
}
}
}

impl Drop for TestFixture {
fn drop(&mut self) {
match std::fs::remove_file(&self.socket_path) {
Ok(_) => {}
Err(e) => {
write!(stderr(), "Error cleaning up `TestFixture`: {e:?}")
.expect("Error writing to stderr");
}
}
}
}
use freyja_test_common::fixtures::GRPCTestFixture;

async fn create_test_grpc_client(
socket_path: PathBuf,
Expand Down Expand Up @@ -332,7 +303,7 @@ mod grpc_data_adapter_tests {

#[tokio::test]
async fn send_request_to_provider() {
let fixture = TestFixture::new();
let fixture = GRPCTestFixture::new();

// Create the Unix Socket
let uds = UnixListener::bind(&fixture.socket_path).unwrap();
Expand Down
4 changes: 2 additions & 2 deletions adapters/digital_twin/grpc_digital_twin_adapter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ tonic = { workspace = true }
freyja-build-common = { workspace = true }

[dev-dependencies]
freyja-test-common = { workspace = true }
tokio-stream = { workspace = true, features = ["net"] }
tower = { workspace = true }
uuid = { workspace = true, features = ["v4"] }
tower = { workspace = true }
Loading

0 comments on commit a8b7816

Please sign in to comment.