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

tests: refactor service tests as standalone #249

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 3 additions & 12 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,24 +54,15 @@ jobs:
sleep 1
done

- name: Create example graph
run: docker exec neo4j bash /db-graph/run-queries.sh

# - name: Install dependencies
# run: cargo build --release

- name: Load Mock Data
run: cargo run --bin mockdb

- name: Run the service
run: |
cargo run > service.log 2>&1 &
sleep 10 # Give the service a moment to start

- name: Run integration tests
run: cargo test

- name: Show service logs if tests fail
if: failure()
run: cat service.log

- name: Tear down Docker Compose
if: always()
working-directory: docker
Expand Down
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ path = "src/service.rs"
name = "watcher"
path = "src/watcher.rs"

[[bin]]
name = "mockdb"
path = "src/mock_db.rs"

[[bench]]
name = "user"
harness = false
Expand Down
60 changes: 28 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,27 +54,20 @@ To get started with Nexus, first set up the required databases: Neo4j and Redis.
1. Clone the repository and navigate to the project directory.
2. Copy the environment template and set up the Docker environment:

```bash
cd docker
cp .env-sample .env
docker-compose up -d
```
```bash
cd docker
cp .env-sample .env
docker-compose up -d
```

3. Populate the Neo4j database with initial data:

```bash
docker exec neo4j bash /db-graph/run-queries.sh
```

Once the `Neo4j` graph database is seeded with data, the next step is to populate the `Redis` database by running the _nexus-service_

> If the Redis cache is empty, the nexus-service will handle it automatically. If not follow the steps of warning section
3. Optionally populate the Neo4j database with initial mock data. For that refer to [Running Tests](#running-tests).

4. Run the Nexus service:

```bash
cargo run
```
```bash
cargo run
```

5. **Access Redis and Neo4j UIs**:
- Redis UI: [http://localhost:8001/redis-stack/browser](http://localhost:8001/redis-stack/browser)
- Neo4J UI: [http://localhost:7474/browser/](http://localhost:7474/browser/)
Expand All @@ -89,7 +82,23 @@ To contribute to Nexus, follow these steps:

### Running Tests

To run all tests:
Running tests requires setting up mock data into Neo4j and Redis.

Use the `mockdb` binary to load the mock data.
```bash
cargo run --bin mockdb [database]
```

`database` is optional and can be either `graph` or `redis`. Not providing any value will sync all the databases.

> If the Redis cache is empty, the nexus-service will handle it automatically. If not follow the steps of warning section

You can optionally pass the `GRAPH_CONTAINER_NAME` env var if your neo4j container in docker has a different name. Defaults to `neo4j`. For example:
```bash
GRAPH_CONTAINER_NAME=nexus-neo4j cargo run --bin mockdb
```

Then to run all tests:

```bash
cargo test
Expand All @@ -110,20 +119,7 @@ cargo bench --bench user get_user_view_by_id

## ⚠️ Troubleshooting

If tests or the development environment seem out of sync, follow these steps to reset:

1. **Reset Neo4j**:

```bash
docker exec neo4j bash -c "cypher-shell -u neo4j -p 12345678 'MATCH (n) DETACH DELETE n;'"
docker exec neo4j bash /db-graph/run-queries.sh
```

2. **Re-index Redis Cache**:

```bash
REINDEX=true cargo run
```
If tests or the development environment seem out of sync, follow the [Running Tests](#running-tests) steps to reload the mock data.

## 🌐 Useful Links

Expand Down
4 changes: 2 additions & 2 deletions benches/setup.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use pubky_nexus::{setup, Config};
use pubky_nexus::{Config, StackManager};
use std::{env, sync::Once};
use tokio::runtime::Runtime;

Expand All @@ -10,7 +10,7 @@ pub fn run_setup() {
env::set_var("RUST_LOG", "error");
rt.block_on(async {
let config = Config::from_env();
setup(&config).await;
StackManager::setup(&config).await;
});
});
}
4 changes: 2 additions & 2 deletions examples/from_file.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use anyhow::Result;
use pubky_nexus::{setup, types::DynError, Config, EventProcessor};
use pubky_nexus::{types::DynError, Config, EventProcessor, StackManager};
use std::fs::File;
use std::io::{self, BufRead};
use std::path::Path;
Expand All @@ -12,7 +12,7 @@ const FILE_PATH: &str = "examples/events.txt";
#[tokio::main]
async fn main() -> Result<(), DynError> {
let config = Config::from_env();
setup(&config).await;
StackManager::setup(&config).await;

let mut event_processor = EventProcessor::from_config(&config).await?;

Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
mod config;
mod db;
pub mod db;
mod error;
pub mod events;
pub mod models;
Expand All @@ -18,6 +18,6 @@ pub use db::kv::traits::RedisOps;
pub use error::{Error, Result};
pub use events::processor::EventProcessor;
pub use reindex::reindex;
pub use setup::setup;
pub use setup::StackManager;

extern crate const_format;
80 changes: 80 additions & 0 deletions src/mock_db.rs
Copy link
Collaborator

Choose a reason for hiding this comment

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

What about if we move that to src/db/mock_db.rs as it is related with db operations?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

since it's a bin I'd rather really have it there.
How much do you insist on it? :D

Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use log::info;

use std::process::Stdio;

use neo4rs::query;

use pubky_nexus::{
db::connectors::redis::get_redis_conn, get_neo4j_graph, reindex, Config, StackManager,
};

#[tokio::main]
async fn main() {
let config = Config::from_env();
StackManager::setup(&config).await;
info!("Running mock db sync");
let args: Vec<String> = std::env::args().collect();
match args.get(1).map(String::as_str) {
Some("graph") => {
MockDB::sync_graph().await;
}
Some("redis") => {
MockDB::sync_redis().await;
}
None => {
MockDB::sync_graph().await;
MockDB::sync_redis().await;
}
Some(_) => {
panic!("Invalid argument. Use 'graph' or 'redis'");
}
}
}

pub struct MockDB {}

impl MockDB {
async fn sync_graph() {
let graph = get_neo4j_graph().expect("Failed to get Neo4j graph connection");

// drop and run the queries again
let drop_all_query = query("MATCH (n) DETACH DELETE n;");
graph
.lock()
.await
.run(drop_all_query)
.await
.expect("Could not drop graph nodes.");

let graph_env = std::env::var("GRAPH_CONTAINER_NAME").unwrap_or("neo4j".to_string());
// Run the run-queries.sh script on the Docker host using docker exec
tokio::process::Command::new("docker")
.args([
"exec",
graph_env.as_str(),
"bash",
"/db-graph/run-queries.sh",
])
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.status()
.await
.expect("Failed to run run-queries.sh");
}

async fn sync_redis() {
// Drop all keys in Redis
let mut redis_conn = get_redis_conn()
.await
.expect("Could not get the redis connection");

redis::cmd("FLUSHALL")
.exec_async(&mut redis_conn)
.await
.expect("Failed to flush Redis");

// Reindex
info!("Starting reindexing process.");
reindex().await;
}
}
8 changes: 4 additions & 4 deletions src/models/post/details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,19 +183,19 @@ impl PostDetails {

#[cfg(test)]
mod tests {
use crate::{setup, Config};
use crate::{Config, StackManager};

use super::*;

const AUTHOR_A_ID: &str = "h3fghnb3x59oh7r53x8y6a5x38oatqyjym9b31ybss17zqdnhcoy";
const REPLY_ID: &str = "2ZECXVXHZBE00";
const POST_ID: &str = "2ZECRNM66G900";

#[tokio::test]
#[tokio_shared_rt::test(shared)]
async fn test_post_details_get_from_graph() {
// Open connections against ddbb
let config = Config::from_env();
setup(&config).await;
StackManager::setup(&config).await;

let _res = PostDetails::get_by_id(AUTHOR_A_ID, REPLY_ID).await.unwrap();
let replies = PostStream::get_post_replies(AUTHOR_A_ID, POST_ID, None, None, None)
.await
Expand Down
6 changes: 3 additions & 3 deletions src/models/user/details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ impl UserDetails {

#[cfg(test)]
mod tests {
use crate::{setup, Config};
use crate::{Config, StackManager};

use super::*;

Expand All @@ -128,10 +128,10 @@ mod tests {
"not_existing_user_id_either", // Does not exist
];

#[tokio::test]
#[tokio_shared_rt::test(shared)]
async fn test_get_by_ids_from_redis() {
let config = Config::from_env();
setup(&config).await;
StackManager::setup(&config).await;

let user_details = UserDetails::get_by_ids(&USER_IDS).await.unwrap();
assert_eq!(user_details.len(), USER_IDS.len());
Expand Down
5 changes: 2 additions & 3 deletions src/models/user/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,15 +145,14 @@ mod tests {
traits::Collection,
user::{UserDetails, UserSearch},
},
setup,
types::{DynError, PubkyId},
Config, RedisOps,
Config, RedisOps, StackManager,
};

#[tokio_shared_rt::test(shared)]
async fn test_put_to_index_no_duplicates() -> Result<(), DynError> {
let config = Config::from_env();
setup(&config).await;
StackManager::setup(&config).await;
// Test that the `put_to_index` method does not add duplicate records to the index
// when called with the same `UserDetails` multiple times.

Expand Down
4 changes: 2 additions & 2 deletions src/service.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use log::info;
use pubky_nexus::{redis_is_empty, reindex, routes, setup, Config};
use pubky_nexus::{redis_is_empty, reindex, routes, Config, StackManager};
use tokio::net::TcpListener;

#[tokio::main]
async fn main() {
let config = Config::from_env();
setup(&config).await;
StackManager::setup(&config).await;

// Reindex if REINDEX is set to true or Redis is empty
let should_reindex = config.reindex || redis_is_empty().await.unwrap_or(false);
Expand Down
Loading
Loading