From 83892a31731be5964c1c56576886d9d866d16432 Mon Sep 17 00:00:00 2001 From: Tarek Date: Wed, 20 Nov 2024 17:26:28 +0200 Subject: [PATCH] feat(fs-index): add integration tests for ark-cli watch functionality Signed-off-by: Tarek --- .github/workflows/build.yml | 9 ++++ data-resource/src/lib.rs | 2 + fs-index/README.md | 14 +++++- fs-index/examples/index_watch.rs | 35 +++++++++++++ integration/ark-cli-watch.sh | 84 ++++++++++++++++++++++++++++++++ 5 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 fs-index/examples/index_watch.rs create mode 100755 integration/ark-cli-watch.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a6a7d947..7701fb74 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,6 +42,9 @@ jobs: - name: Build Release run: cargo build --verbose --release + - name: Run `ark-cli watch` test + run: ./integration/ark-cli-watch.sh + - name: Install JDK uses: actions/setup-java@v4.2.1 with: @@ -71,6 +74,9 @@ jobs: - name: Run tests run: cargo test --workspace --verbose + - name: Run `ark-cli watch` test + run: ./integration/ark-cli-watch.sh + - name: Install JDK uses: actions/setup-java@v4.2.1 with: @@ -100,6 +106,9 @@ jobs: - name: Run tests run: cargo test --workspace --verbose + - name: Run `ark-cli watch` test + run: ./integration/ark-cli-watch.sh + - name: Install JDK uses: actions/setup-java@v4.2.1 with: diff --git a/data-resource/src/lib.rs b/data-resource/src/lib.rs index ea7426c3..9368101c 100644 --- a/data-resource/src/lib.rs +++ b/data-resource/src/lib.rs @@ -25,6 +25,8 @@ pub trait ResourceId: + Hash + Serialize + DeserializeOwned + + Sync + + Send { /// Computes the resource identifier from the given file path fn from_path>(file_path: P) -> Result; diff --git a/fs-index/README.md b/fs-index/README.md index ca3fb565..427db943 100644 --- a/fs-index/README.md +++ b/fs-index/README.md @@ -15,6 +15,10 @@ The most important struct in this crate is `ResourceIndex` which comes with: - `get_resource_by_path`: Query a resource from the index by its path. - **Selective API** - `update_one`: Method to manually update a specific resource by selectively rescanning a single file. +- **Watch API** (Enable with `watch` feature) + - `watch`: Method to watch a directory for changes and update the index accordingly. + +> **Note:** To see the watch API in action, run the `index_watch` example or check `ark-cli watch` command. ## Custom Serialization @@ -30,8 +34,14 @@ The `ResourceIndex` struct includes a custom serialization implementation to avo To get started, take a look at the examples in the `examples/` directory. -To run a specific example: +To run a specific example, run this command from the root of the project or the root of the crate: + +```shell +cargo run --example +``` + +For example, to run the `index_watch` example: ```shell -cargo run --example resource_index +cargo run --example index_watch ``` diff --git a/fs-index/examples/index_watch.rs b/fs-index/examples/index_watch.rs new file mode 100644 index 00000000..ef01c5b8 --- /dev/null +++ b/fs-index/examples/index_watch.rs @@ -0,0 +1,35 @@ +use std::path::Path; + +use anyhow::Result; +use futures::{pin_mut, StreamExt}; + +use dev_hash::Blake3; +use fs_index::{watch_index, WatchEvent}; + +/// A simple example of using `watch_index` to monitor a directory for file +/// changes. This asynchronously listens for updates and prints the paths of +/// changed files. +#[tokio::main] +async fn main() -> Result<()> { + env_logger::init(); + + // Change this to the path of the directory you want to watch + let root = Path::new("test-assets"); + + let stream = watch_index::<_, Blake3>(root); + + pin_mut!(stream); // needed for iteration + + while let Some(value) = stream.next().await { + match value { + WatchEvent::UpdatedOne(update) => { + println!("Updated file: {:?}", update); + } + WatchEvent::UpdatedAll(update) => { + println!("Updated all: {:?}", update); + } + } + } + + Ok(()) +} diff --git a/integration/ark-cli-watch.sh b/integration/ark-cli-watch.sh new file mode 100755 index 00000000..58d935f8 --- /dev/null +++ b/integration/ark-cli-watch.sh @@ -0,0 +1,84 @@ +#!/bin/bash + +# Set up paths +WATCH_DIR="test-assets" +OUTPUT_FILE="ark-watch-output.txt" +INDEX_FILE="$WATCH_DIR/.ark/index" +ARK_CLI="./target/release/ark-cli" + +# Function to check the index file content +check_index() { + # Expecting a certain number of resources based on the operations done + expected_count=$1 + shift + expected_resources=("$@") + + # Get the actual count of resources in the index + resources_count=$(jq '.resources | keys | length' "$INDEX_FILE") + + if [ "$resources_count" -ne "$expected_count" ]; then + echo "Index sanity check failed: expected $expected_count resources, found $resources_count" + exit 1 + fi + + # Check the paths of the resources in the index + for resource in "${expected_resources[@]}"; do + if ! jq -e ".resources | has(\"$resource\")" "$INDEX_FILE" > /dev/null; then + echo "Index sanity check failed: resource \"$resource\" not found in index." + exit 1 + fi + done + + echo "Current resources in index:" + jq '.resources' "$INDEX_FILE" +} + +# Start `ark-cli watch` in the background and capture output +echo "Starting ark-cli watch on $WATCH_DIR..." +$ARK_CLI watch "$WATCH_DIR" > "$OUTPUT_FILE" & +WATCH_PID=$! +sleep 1 # Wait a bit to ensure the watch command is up + +# Initial sanity check for index file +check_index 2 "test.pdf" "lena.jpg" # Initially should contain lena.jpg and test.pdf + +echo "Modifying files in $WATCH_DIR..." + +# Step 1: Copy `lena.jpg` to `lena_copy.jpg` +cp "$WATCH_DIR/lena.jpg" "$WATCH_DIR/lena_copy.jpg" +sleep 3 + +check_index 3 "lena.jpg" "lena_copy.jpg" "test.pdf" + +# Step 2: Remove `test.pdf` +rm "$WATCH_DIR/test.pdf" +sleep 3 + +check_index 2 "lena.jpg" "lena_copy.jpg" + +# Step 3: Create a new empty file `note.txt` +touch "$WATCH_DIR/note.txt" +sleep 3 + +# Final index check after all operations +echo "Verifying final index state..." +check_index 3 "lena.jpg" "lena_copy.jpg" "note.txt" # Expect three resources now + +# Allow `ark-cli watch` time to process and then kill it +sleep 1 +kill $WATCH_PID + +# Wait briefly for output to complete +wait $WATCH_PID 2>/dev/null + +# Read and verify the ark-watch-output.txt contents +echo "Checking ark-cli watch output..." +expected_change_count=3 # Three file changes done +actual_change_count=$(grep -c "Index updated with a single file change" "$OUTPUT_FILE") + +if [ "$actual_change_count" -ne "$expected_change_count" ]; then + echo "Output verification failed: expected $expected_change_count updates, found $actual_change_count" + exit 1 +fi + +echo "All checks passed successfully!"