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

Feat : add testing fixtures and a basic test #52

Merged
merged 26 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
726f1ed
feat : added tests for increasing coverage
ocdbytes Jul 23, 2024
b3a80b0
feat : added mongo db tests and fixtures and updated the ci for tests
ocdbytes Jul 24, 2024
5826d44
update : removed unwanted fixtures
ocdbytes Jul 24, 2024
0e70fff
update : removed unwanted fixtures
ocdbytes Jul 24, 2024
97f1f21
update : added mongo db runner in ci
ocdbytes Jul 24, 2024
a64613c
update : added mongo db runner in ci
ocdbytes Jul 24, 2024
db472d5
update : added mongo db runner in ci
ocdbytes Jul 24, 2024
15541ef
update : updated with new changes and ci
ocdbytes Jul 25, 2024
fc7d493
update : updated test cases for s3 client
ocdbytes Jul 26, 2024
9a101ba
update : added .env.test file in the commit
ocdbytes Jul 26, 2024
906a1eb
feat : added database necessary tests
ocdbytes Jul 26, 2024
65d66e6
feat : added database necessary tests
ocdbytes Jul 26, 2024
20d82c3
Revert "feat : added database necessary tests"
ocdbytes Jul 26, 2024
63bc846
Revert "feat : added database necessary tests"
ocdbytes Jul 26, 2024
f36b483
update: Replaced Build_Config Fixture with TestConfigBuilder
heemankv Jul 26, 2024
8b7e68f
update : config update
ocdbytes Jul 26, 2024
74fea52
update : test_put_and_get_data_s3 test
ocdbytes Jul 26, 2024
385974d
update: moved testconfigbuilder to tests/config.rs & added docs , dro…
heemankv Jul 29, 2024
c01c990
Merge branch 'main' into feat/increasing-test-coverage
heemankv Jul 31, 2024
b31212c
feat : updated test config and added config type to aws s3 config
ocdbytes Aug 2, 2024
ae2d4d9
chore: resolved pr comments
ocdbytes Aug 3, 2024
67141ba
Update crates/orchestrator/src/tests/database/mod.rs
ocdbytes Aug 3, 2024
6c9b68e
Merge branch 'main' into feat/increasing-test-coverage
ocdbytes Aug 3, 2024
20a480e
feat : lint fix
ocdbytes Aug 3, 2024
7f01895
fix : coverage tests fix
ocdbytes Aug 5, 2024
44aecd7
fix : test fix
ocdbytes Aug 5, 2024
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
33 changes: 33 additions & 0 deletions .env.test.example
apoorvsadana marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
HOST=
PORT=
DATABASE_URL=
MADARA_RPC_URL=
DA_LAYER=
SETTLEMENT_LAYER=

# Ethereum
ETHEREUM_PRIVATE_KEY=
ETHEREUM_RPC_URL=
MEMORY_PAGES_CONTRACT_ADDRESS=
STARKNET_SOLIDITY_CORE_CONTRACT_ADDRESS=


# Starknet
STARKNET_PUBLIC_KEY=
STARNET_PRIVATE_KEY=
STARKNET_RPC_URL=
STARKNET_CAIRO_CORE_CONTRACT_ADDRESS=

# MongoDB connection string
MONGODB_CONNECTION_STRING=

# SQS
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=

# S3
AWS_S3_BUCKET_NAME=
AWS_S3_BUCKET_REGION=

# AWS Local Stack URL
AWS_ENDPOINT_URL=
31 changes: 31 additions & 0 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,21 @@ jobs:
# sadly, for now we have to "rebuild" for the coverage
runs-on: ubuntu-latest

services:
localstack:
image: localstack/localstack
env:
SERVICES: s3, sqs
DEFAULT_REGION: us-east-1
AWS_ACCESS_KEY_ID: "AWS_ACCESS_KEY_ID"
AWS_SECRET_ACCESS_KEY: "AWS_SECRET_ACCESS_KEY"
ports:
- 4566:4566
mongodb:
image: mongo:latest
ports:
- 27017:27017

steps:
- uses: actions/checkout@v3

Expand All @@ -26,6 +41,22 @@ jobs:

- name: Run llvm-cov
run: |
echo 'AWS_ACCESS_KEY_ID="AWS_ACCESS_KEY_ID"' >> .env.test
echo 'AWS_SECRET_ACCESS_KEY="AWS_SECRET_ACCESS_KEY"' >> .env.test
echo 'AWS_S3_BUCKET_NAME="madara-orchestrator-test-bucket"' >> .env.test
echo 'AWS_S3_BUCKET_REGION="us-east-1"' >> .env.test
echo 'AWS_ENDPOINT_URL="http://localhost.localstack.cloud:4566"' >> .env.test
echo 'MADARA_RPC_URL="http://localhost:3000"' >> .env.test
echo 'ETHEREUM_RPC_URL="http://localhost:3001"' >> .env.test
echo 'MEMORY_PAGES_CONTRACT_ADDRESS="0x000000000000000000000000000000000001dead"' >> .env.test
echo 'PRIVATE_KEY="0xdead"' >> .env.test
echo 'ETHEREUM_PRIVATE_KEY="0x000000000000000000000000000000000000000000000000000000000000beef"' >> .env.test
echo 'STARKNET_SOLIDITY_CORE_CONTRACT_ADDRESS="0x000000000000000000000000000000000002dead"' >> .env.test
echo 'DA_LAYER="ethereum"' >> .env.test
echo 'PROVER_SERVICE="sharp"' >> .env.test
echo 'SETTLEMENT_LAYER="ethereum"' >> .env.test
echo 'DATA_STORAGE="s3"' >> .env.test
echo 'MONGODB_CONNECTION_STRING="mongodb://localhost:27017"' >> .env.test
apoorvsadana marked this conversation as resolved.
Show resolved Hide resolved
cargo llvm-cov nextest --release --lcov --output-path lcov.info --test-threads=1

- name: Upload coverage to codecov.io
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
.env
.idea
.DS_Store
.env.test
apoorvsadana marked this conversation as resolved.
Show resolved Hide resolved

*.code-workspace
.vscode
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
- Function to calculate the kzg proof of x_0.
- Tests for updating the state.
- Function to update the state and publish blob on ethereum in state update job.
- Fixtures for testing.

## Changed

- GitHub's coverage CI yml file for localstack and db testing.

## Removed

- `fetch_from_test` argument
Expand Down
10 changes: 6 additions & 4 deletions crates/orchestrator/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ pub async fn config_force_init(config: Config) {
}

/// Builds the DA client based on the environment variable DA_LAYER
async fn build_da_client() -> Box<dyn DaClient + Send + Sync> {
pub async fn build_da_client() -> Box<dyn DaClient + Send + Sync> {
match get_env_var_or_panic("DA_LAYER").as_str() {
"ethereum" => {
let config = EthereumDaConfig::new_from_env();
Expand All @@ -159,23 +159,25 @@ async fn build_da_client() -> Box<dyn DaClient + Send + Sync> {
}

/// Builds the prover service based on the environment variable PROVER_SERVICE
fn build_prover_service(settings_provider: &impl SettingsProvider) -> Box<dyn ProverClient> {
pub fn build_prover_service(settings_provider: &impl SettingsProvider) -> Box<dyn ProverClient> {
match get_env_var_or_panic("PROVER_SERVICE").as_str() {
"sharp" => Box::new(SharpProverService::with_settings(settings_provider)),
_ => panic!("Unsupported prover service"),
}
}

/// Builds the settlement client depending on the env variable SETTLEMENT_LAYER
async fn build_settlement_client(settings_provider: &impl SettingsProvider) -> Box<dyn SettlementClient + Send + Sync> {
pub async fn build_settlement_client(
settings_provider: &impl SettingsProvider,
) -> Box<dyn SettlementClient + Send + Sync> {
match get_env_var_or_panic("SETTLEMENT_LAYER").as_str() {
"ethereum" => Box::new(EthereumSettlementClient::with_settings(settings_provider)),
"starknet" => Box::new(StarknetSettlementClient::with_settings(settings_provider).await),
_ => panic!("Unsupported Settlement layer"),
}
}

async fn build_storage_client() -> Box<dyn DataStorage + Send + Sync> {
pub async fn build_storage_client() -> Box<dyn DataStorage + Send + Sync> {
match get_env_var_or_panic("DATA_STORAGE").as_str() {
"s3" => Box::new(AWSS3::new(AWSS3Config::new_from_env()).await),
_ => panic!("Unsupported Storage Client"),
Expand Down
24 changes: 0 additions & 24 deletions crates/orchestrator/src/controllers/jobs_controller.rs

This file was deleted.

3 changes: 0 additions & 3 deletions crates/orchestrator/src/controllers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,2 @@
/// Errors
mod errors;

/// Job controllers
pub mod jobs_controller;
5 changes: 5 additions & 0 deletions crates/orchestrator/src/data_storage/aws_s3/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ pub struct AWSS3Config {
pub s3_bucket_name: String,
/// S3 Bucket region
pub s3_bucket_region: String,
/// Endpoint url
#[cfg(test)]
pub endpoint_url: String,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this only used in tests? Is there no equivalent notion when connecting to AWS directly? It would be better to avoid this difference between production and testing, if possible.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Localstack endpoint URL : http://localhost.localstack.cloud:4566
AWS endpoint URL. : https://s3.{region}.amazonaws.com/{bucket-name}/{key}

We are using localstack for mocking AWS locally.
Localstack requires endpoint_url to get connected.

Connection to AWS doesn't necessarily require the endpoint url as shown here.
Rather, the connection to localstack does as shown here.

Hence this implementation is under the tests flag.
What do you propose as a solution?,
Do you think changing prod code as how tests are written (adding endpoint url on prod just because it's available on tests) is a valid way to go ?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But specifying the endpoint is still a possibility on AWS, right? I'm not in favor of "modifying production code", but here it's just that you have 2 different ways of connecting: either you specify the region, bucket key etc or you provide the endpoint directly. It turns out that localstack only supports the endpoint method, sure.

In effect you have two usable connection solutions => you could use an enumeration to support both features, for example giving priority to the endpoint method if someone wants to hardcode it for some reason and then support the default method as a backup. This way, your code is the same for testing vs prod and you support two methods to connect to AWS. WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @odesenfans
I agree with your implementation and it is more cleaner. I will implement this and push the code.

}

/// Implementation of `DataStorageConfig` for `AWSS3Config`
Expand All @@ -23,6 +26,8 @@ impl DataStorageConfig for AWSS3Config {
s3_key_secret: get_env_var_or_panic("AWS_SECRET_ACCESS_KEY"),
s3_bucket_name: get_env_var_or_panic("AWS_S3_BUCKET_NAME"),
s3_bucket_region: get_env_var_or_panic("AWS_S3_BUCKET_REGION"),
#[cfg(test)]
endpoint_url: get_env_var_or_panic("AWS_ENDPOINT_URL"),
apoorvsadana marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
17 changes: 15 additions & 2 deletions crates/orchestrator/src/data_storage/aws_s3/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ pub struct AWSS3 {
impl AWSS3 {
/// Initializes a new AWS S3 client by passing the config
/// and returning it.
#[allow(dead_code)]
pub async fn new(config: AWSS3Config) -> Self {
// AWS cred building
let credentials = Credentials::new(
Expand All @@ -33,7 +32,15 @@ impl AWSS3 {
"loaded_from_custom_env",
);
let region = Region::new(config.s3_bucket_region.clone().to_string());
let conf_builder = Builder::new().region(region).credentials_provider(credentials);

#[allow(unused_mut)]
let mut conf_builder = Builder::new().region(region).credentials_provider(credentials).force_path_style(true);

#[cfg(test)]
{
conf_builder = conf_builder.endpoint_url(config.endpoint_url.clone().to_string());
}

let conf = conf_builder.build();

// Building AWS S3 config
Expand Down Expand Up @@ -69,4 +76,10 @@ impl DataStorage for AWSS3 {

Ok(())
}

#[cfg(test)]
async fn build_test_bucket(&self, bucket_name: &str) -> Result<()> {
self.client.create_bucket().bucket(bucket_name).send().await?;
Ok(())
}
}
2 changes: 2 additions & 0 deletions crates/orchestrator/src/data_storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ use mockall::automock;
pub trait DataStorage: Send + Sync {
async fn get_data(&self, key: &str) -> Result<Bytes>;
async fn put_data(&self, data: Bytes, key: &str) -> Result<()>;
#[cfg(test)]
async fn build_test_bucket(&self, bucket_name: &str) -> Result<()>;
}

/// **DataStorageConfig** : Trait method to represent the config struct needed for
Expand Down
4 changes: 4 additions & 0 deletions crates/orchestrator/src/database/mongodb/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ impl MongoDb {
MongoDb { client }
}

pub fn client(&self) -> Client {
self.client.clone()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: when I see the call to clone(), my first reflex is to check the cost of this operation. I looked at the docs of MongoDB and saw that Client uses an Arc internally, so this is fine. But it is worth adding a comment explaining why this is fine, because for non Arc-based types doing

pub fn client(&self) -> &Client {
  &self.client
}

and then letting the caller decide if he wants to clone is better.

TL;DR, add a comment to explain that Client uses Arc and therefore is cheap to clone.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid and a great catch,
added docs to describe that client uses Arc.

}

fn get_job_collection(&self) -> Collection<JobItem> {
self.client.database("orchestrator").collection("jobs")
}
Expand Down
4 changes: 2 additions & 2 deletions crates/orchestrator/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// Config of the service. Contains configurations for DB, Queues and other services.
pub mod config;
mod constants;
pub mod constants;
/// Controllers for the routes
pub mod controllers;
/// Contains the trait that implements the fetching functions
Expand All @@ -17,6 +17,6 @@ pub mod queue;
/// Contains the routes for the service
pub mod routes;
#[cfg(test)]
mod tests;
pub mod tests;
/// Contains workers which act like cron jobs
pub mod workers;
4 changes: 2 additions & 2 deletions crates/orchestrator/src/queue/job_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use uuid::Uuid;
use crate::config::config;
use crate::jobs::{process_job, verify_job};

const JOB_PROCESSING_QUEUE: &str = "madara_orchestrator_job_processing_queue";
const JOB_VERIFICATION_QUEUE: &str = "madara_orchestrator_job_verification_queue";
pub const JOB_PROCESSING_QUEUE: &str = "madara_orchestrator_job_processing_queue";
pub const JOB_VERIFICATION_QUEUE: &str = "madara_orchestrator_job_verification_queue";

#[derive(Debug, Serialize, Deserialize)]
pub struct JobQueueMessage {
Expand Down
14 changes: 2 additions & 12 deletions crates/orchestrator/src/routes.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
use axum::http::StatusCode;
use axum::response::IntoResponse;
use axum::routing::{get, post};
use axum::routing::get;
use axum::Router;

use crate::controllers::jobs_controller;

pub fn app_router() -> Router {
Router::new()
.route("/health", get(root))
.nest("/v1/dev", dev_routes())
.nest("/v1/job", job_routes())
.fallback(handler_404)
Router::new().route("/health", get(root)).nest("/v1/dev", dev_routes()).fallback(handler_404)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this change related to the PR?

Copy link
Contributor

@heemankv heemankv Jul 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a valid concern,
While the tests for Job_controller were being written it was realised that we are not using it anymore and hence it can be deleted, we agree, ideally this is to be done on a separate PR.

Proposed Solution :

  • Have stricter decouples of PR from next time.
  • Keep the commit with this PR.
  • Mention removal of job_controller in the CHANGELOG.

WDYT ?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can keep it in this PR, but mention it in the changelog and in the PR description.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure

}

async fn root() -> &'static str {
Expand All @@ -21,10 +15,6 @@ async fn handler_404() -> impl IntoResponse {
(StatusCode::NOT_FOUND, "The requested resource was not found")
}

fn job_routes() -> Router {
Router::new().route("/create_job", post(jobs_controller::create_job))
}

fn dev_routes() -> Router {
Router::new()
}
49 changes: 47 additions & 2 deletions crates/orchestrator/src/tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,21 @@ use std::sync::Arc;
use ::uuid::Uuid;
use constants::*;
use da_client_interface::MockDaClient;
use mongodb::Client;
use prover_client_interface::MockProverClient;
use rstest::*;
use settlement_client_interface::MockSettlementClient;
use starknet::providers::jsonrpc::HttpTransport;
use starknet::providers::JsonRpcClient;
use url::Url;
use utils::env_utils::get_env_var_or_panic;
use utils::settings::default::DefaultSettingsProvider;

use crate::config::Config;
use crate::config::{build_storage_client, config_force_init, Config};
use crate::data_storage::MockDataStorage;
use crate::database::MockDatabase;
use crate::database::mongodb::config::MongoDbConfig;
use crate::database::mongodb::MongoDb;
use crate::database::{DatabaseConfig, MockDatabase};
use crate::jobs::types::JobStatus::Created;
use crate::jobs::types::JobType::DataSubmission;
use crate::jobs::types::{ExternalId, JobItem};
Expand Down Expand Up @@ -74,3 +79,43 @@ pub fn custom_job_item(default_job_item: JobItem, #[default(String::from("0"))]

job_item
}

/// For implementation of integration tests
#[fixture]
pub async fn build_config() -> color_eyre::Result<()> {
// Getting .env.test variables
dotenvy::from_filename("../.env.test")?;

// init starknet client
let provider = JsonRpcClient::new(HttpTransport::new(
Url::parse(get_env_var_or_panic("MADARA_RPC_URL").as_str()).expect("Failed to parse URL"),
));

// init database
let database = Box::new(MongoDb::new(MongoDbConfig::new_from_env()).await);

// init the queue
let queue = Box::new(crate::queue::sqs::SqsQueue {});

let da_client = crate::config::build_da_client().await;
let settings_provider = DefaultSettingsProvider {};
let settlement_client = crate::config::build_settlement_client(&settings_provider).await;
let prover_client = crate::config::build_prover_service(&settings_provider);
let storage_client = build_storage_client().await;

// building a test bucket :
storage_client.build_test_bucket(&get_env_var_or_panic("AWS_S3_BUCKET_NAME")).await?;

let config =
Config::new(Arc::new(provider), da_client, prover_client, settlement_client, database, queue, storage_client);
config_force_init(config).await;

Ok(())
}

pub async fn drop_database() -> color_eyre::Result<()> {
let db_client: Client = MongoDb::new(MongoDbConfig::new_from_env()).await.client();
// dropping `jobs` collection.
db_client.database("orchestrator").collection::<JobItem>("jobs").drop(None).await?;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Careful that you'll need to add every future collection in here as well. It might be better to just drop every collection under the orchestrator DB.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid, changed to dropping all the collections for now.

  • Added comment to how to change to specific collection.

Ok(())
}
Loading
Loading