From 7f09ab79bb6248615cdf49b5477601db46e1e65e Mon Sep 17 00:00:00 2001 From: Spencerjibz <=spencernajib2@gmail.com> Date: Fri, 3 Nov 2023 08:27:51 +0000 Subject: [PATCH 01/21] Add coverage workflow to measure code quality --- .github/workflows/coverage.yml | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .github/workflows/coverage.yml diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 0000000..e9fc61c --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,36 @@ +name: Code Coverage +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + override: true + - uses: actions-rs/cargo@v1 + + with: + command: test + args: --all-features --no-fail-fast + env: + CARGO_INCREMENTAL: "0" + RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests" + RUSTDOCFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests" + - uses: actions-rs/grcov@v0.1 + id: coverage + + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v3 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + with: + directory: ${{steps.coverage.outputs.report}} From 1f604202fac07efcb291f8e5d54795abbe1e27c1 Mon Sep 17 00:00:00 2001 From: Spencerjibz <=spencernajib2@gmail.com> Date: Fri, 3 Nov 2023 08:45:28 +0000 Subject: [PATCH 02/21] Add GRCov configuration and upload coverage reports to Codecov --- .github/grcov.yml | 6 ++++++ .github/workflows/coverage.yml | 2 ++ 2 files changed, 8 insertions(+) create mode 100644 .github/grcov.yml diff --git a/.github/grcov.yml b/.github/grcov.yml new file mode 100644 index 0000000..a8d46b7 --- /dev/null +++ b/.github/grcov.yml @@ -0,0 +1,6 @@ +branch: true +ignore-not-existing: true +llvm: true +filter: covered +output-type: lcov +output-path: ./coverage diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index e9fc61c..63efd7b 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -27,6 +27,8 @@ jobs: RUSTDOCFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests" - uses: actions-rs/grcov@v0.1 id: coverage + with: + config: .github/grcov.yml - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v3 From 30ebb5f0ab26da21f6eded4d9f60b9732cdda161 Mon Sep 17 00:00:00 2001 From: Spencerjibz <=spencernajib2@gmail.com> Date: Fri, 3 Nov 2023 08:51:14 +0000 Subject: [PATCH 03/21] add caching to codecov workflow --- .github/workflows/coverage.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 63efd7b..7d59fab 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -16,6 +16,16 @@ jobs: with: toolchain: nightly override: true + - uses: actions/cache@v3 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}-coverage + - uses: actions-rs/cargo@v1 with: @@ -35,4 +45,4 @@ jobs: env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} with: - directory: ${{steps.coverage.outputs.report}} + files: coverage/*.lcov From 48028395695ac68d4c1caddd054aed3711999383 Mon Sep 17 00:00:00 2001 From: Spencerjibz <=spencernajib2@gmail.com> Date: Fri, 3 Nov 2023 09:02:33 +0000 Subject: [PATCH 04/21] check for coverage files --- .github/workflows/coverage.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 7d59fab..b2d7364 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -35,14 +35,19 @@ jobs: CARGO_INCREMENTAL: "0" RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests" RUSTDOCFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests" + - name: Download grcov + run: | + mkdir -p "${HOME}/.local/bin" + curl -sL https://github.com/mozilla/grcov/releases/download/v0.8.10/grcov-x86_64-unknown-linux-gnu.tar.bz2 | tar jxf - -C "${HOME}/.local/bin" + echo "$HOME/.local/bin" >> $GITHUB_PATH - uses: actions-rs/grcov@v0.1 id: coverage with: config: .github/grcov.yml + - name: List coverage files + run: ls coverage -lah - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v3 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - with: - files: coverage/*.lcov From 87598175f24706c04c2d3d7300a3c6d6ac8bda3a Mon Sep 17 00:00:00 2001 From: Spencerjibz <=spencernajib2@gmail.com> Date: Fri, 3 Nov 2023 09:16:36 +0000 Subject: [PATCH 05/21] modified grcov settings --- .github/grcov.yml | 1 - .github/workflows/coverage.yml | 53 ---------------------------------- 2 files changed, 54 deletions(-) delete mode 100644 .github/workflows/coverage.yml diff --git a/.github/grcov.yml b/.github/grcov.yml index a8d46b7..52cae81 100644 --- a/.github/grcov.yml +++ b/.github/grcov.yml @@ -1,6 +1,5 @@ branch: true ignore-not-existing: true llvm: true -filter: covered output-type: lcov output-path: ./coverage diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml deleted file mode 100644 index b2d7364..0000000 --- a/.github/workflows/coverage.yml +++ /dev/null @@ -1,53 +0,0 @@ -name: Code Coverage -on: - push: - branches: - - main - pull_request: - branches: - - main - -jobs: - lint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly - override: true - - uses: actions/cache@v3 - with: - path: | - ~/.cargo/bin/ - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - target/ - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}-coverage - - - uses: actions-rs/cargo@v1 - - with: - command: test - args: --all-features --no-fail-fast - env: - CARGO_INCREMENTAL: "0" - RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests" - RUSTDOCFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests" - - name: Download grcov - run: | - mkdir -p "${HOME}/.local/bin" - curl -sL https://github.com/mozilla/grcov/releases/download/v0.8.10/grcov-x86_64-unknown-linux-gnu.tar.bz2 | tar jxf - -C "${HOME}/.local/bin" - echo "$HOME/.local/bin" >> $GITHUB_PATH - - uses: actions-rs/grcov@v0.1 - id: coverage - with: - config: .github/grcov.yml - - - name: List coverage files - run: ls coverage -lah - - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v3 - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} From e462a6c98f4a87641701a2e65511c446b2d84c7d Mon Sep 17 00:00:00 2001 From: Spencerjibz <=spencernajib2@gmail.com> Date: Fri, 3 Nov 2023 09:19:09 +0000 Subject: [PATCH 06/21] modified grcov settings --- .github/workflows/codecov.yml | 56 +++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 .github/workflows/codecov.yml diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml new file mode 100644 index 0000000..9d61e21 --- /dev/null +++ b/.github/workflows/codecov.yml @@ -0,0 +1,56 @@ +name: Code Coverage +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + override: true + components: llvm-tools-preview + - uses: actions/cache@v3 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}-coverage + + - uses: actions-rs/cargo@v1 + + with: + command: test + args: --all-features --no-fail-fast + env: + CARGO_INCREMENTAL: "0" + RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests" + RUSTDOCFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests" + - name: Download grcov + run: | + mkdir -p "${HOME}/.local/bin" + curl -sL https://github.com/mozilla/grcov/releases/download/v0.8.10/grcov-x86_64-unknown-linux-gnu.tar.bz2 | tar jxf - -C "${HOME}/.local/bin" + echo "$HOME/.local/bin" >> $GITHUB_PATH + - uses: actions-rs/grcov@v0.1 + id: coverage + with: + config: .github/grcov.yml + + - name: List coverage files + run: ls ./coverage -lah + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v3 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + with: + files: coverage/*.lcov From 37914830161d8e0d11fde2ab61034bc741993492 Mon Sep 17 00:00:00 2001 From: Spencerjibz <=spencernajib2@gmail.com> Date: Fri, 3 Nov 2023 09:24:21 +0000 Subject: [PATCH 07/21] Update output-path in grcov.yml and codecov.yml for coverage files --- .github/grcov.yml | 2 +- .github/workflows/codecov.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/grcov.yml b/.github/grcov.yml index 52cae81..4c13722 100644 --- a/.github/grcov.yml +++ b/.github/grcov.yml @@ -2,4 +2,4 @@ branch: true ignore-not-existing: true llvm: true output-type: lcov -output-path: ./coverage +output-path: coverage diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 9d61e21..cbf1b9e 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -47,7 +47,7 @@ jobs: config: .github/grcov.yml - name: List coverage files - run: ls ./coverage -lah + run: ls coverage -lah - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v3 env: From b54bbcc6c19c364c3e79fc360afec526caa7a923 Mon Sep 17 00:00:00 2001 From: Spencerjibz <=spencernajib2@gmail.com> Date: Fri, 3 Nov 2023 09:28:29 +0000 Subject: [PATCH 08/21] Commit changes to Codecov workflow to use grcov output --- .github/workflows/codecov.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index cbf1b9e..45ca6d8 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -47,10 +47,10 @@ jobs: config: .github/grcov.yml - name: List coverage files - run: ls coverage -lah + run: cat ${{steps.coverage.outputs.report}} && ls ${{steps.coverage.outputs.report}} - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v3 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} with: - files: coverage/*.lcov + files: ${{steps.coverage.outputs.report}}/*.lcov From a186c9c4c9662ad50d6417bd6c3658942fec28f5 Mon Sep 17 00:00:00 2001 From: Spencerjibz <=spencernajib2@gmail.com> Date: Fri, 3 Nov 2023 09:39:22 +0000 Subject: [PATCH 09/21] modified grcov settings --- .github/grcov.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/grcov.yml b/.github/grcov.yml index 4c13722..6b45cb2 100644 --- a/.github/grcov.yml +++ b/.github/grcov.yml @@ -2,4 +2,8 @@ branch: true ignore-not-existing: true llvm: true output-type: lcov -output-path: coverage +output-path: coverage/tests.Icov +ignore: + - "/*" + - "C:/*" + - "../*" From 6e213541de0e13207ca90be8f76c9b1fcd6dfa91 Mon Sep 17 00:00:00 2001 From: Spencerjibz <=spencernajib2@gmail.com> Date: Fri, 3 Nov 2023 09:42:35 +0000 Subject: [PATCH 10/21] modified grcov settings --- .github/grcov.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/grcov.yml b/.github/grcov.yml index 6b45cb2..abb75f5 100644 --- a/.github/grcov.yml +++ b/.github/grcov.yml @@ -2,8 +2,4 @@ branch: true ignore-not-existing: true llvm: true output-type: lcov -output-path: coverage/tests.Icov -ignore: - - "/*" - - "C:/*" - - "../*" +output-path: coverage/tests.lcov From 29dee6404823f9177ad49be449780a1cbec91ece Mon Sep 17 00:00:00 2001 From: Spencerjibz <=spencernajib2@gmail.com> Date: Fri, 3 Nov 2023 09:45:21 +0000 Subject: [PATCH 11/21] modified grcov settings --- .github/grcov.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/grcov.yml b/.github/grcov.yml index abb75f5..429df90 100644 --- a/.github/grcov.yml +++ b/.github/grcov.yml @@ -2,4 +2,8 @@ branch: true ignore-not-existing: true llvm: true output-type: lcov -output-path: coverage/tests.lcov +output-path: ./coverage/tests.lcov +ignore: + - "/*" + - "C:/*" + - "../*" From a5a8538e3ec5b0351d32cd44c55f347e3b5e6f48 Mon Sep 17 00:00:00 2001 From: Spencerjibz <=spencernajib2@gmail.com> Date: Fri, 3 Nov 2023 09:54:06 +0000 Subject: [PATCH 12/21] modified grcov settings --- .github/grcov.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/grcov.yml b/.github/grcov.yml index 429df90..4c13722 100644 --- a/.github/grcov.yml +++ b/.github/grcov.yml @@ -2,8 +2,4 @@ branch: true ignore-not-existing: true llvm: true output-type: lcov -output-path: ./coverage/tests.lcov -ignore: - - "/*" - - "C:/*" - - "../*" +output-path: coverage From 69c20d6b5a4b7126a0788dae74f55f4c8d6bd722 Mon Sep 17 00:00:00 2001 From: Spencerjibz <=spencernajib2@gmail.com> Date: Fri, 3 Nov 2023 09:57:45 +0000 Subject: [PATCH 13/21] modified grcov settings --- .github/workflows/codecov.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 45ca6d8..9f58f1c 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -47,7 +47,7 @@ jobs: config: .github/grcov.yml - name: List coverage files - run: cat ${{steps.coverage.outputs.report}} && ls ${{steps.coverage.outputs.report}} + run: cat ${{steps.coverage.outputs.report}} >> ${{steps.coverage.outputs.report}}/coverage.Icov - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v3 env: From 1e5ca4323f000ff0e8ef79eef120dac12ad2db30 Mon Sep 17 00:00:00 2001 From: Spencerjibz <=spencernajib2@gmail.com> Date: Fri, 3 Nov 2023 10:00:12 +0000 Subject: [PATCH 14/21] modified grcov settings --- .github/workflows/codecov.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 9f58f1c..5b4b3fc 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -47,10 +47,10 @@ jobs: config: .github/grcov.yml - name: List coverage files - run: cat ${{steps.coverage.outputs.report}} >> ${{steps.coverage.outputs.report}}/coverage.Icov + run: cat ${{steps.coverage.outputs.report}} >> coverage.Icov - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v3 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} with: - files: ${{steps.coverage.outputs.report}}/*.lcov + files: ${{steps.coverage.outputs.report}}.lcov From 6f8875f655b6069129edcf66455085de740eaad4 Mon Sep 17 00:00:00 2001 From: Spencerjibz <=spencernajib2@gmail.com> Date: Fri, 3 Nov 2023 10:01:43 +0000 Subject: [PATCH 15/21] modified grcov settings --- .github/workflows/codecov.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 5b4b3fc..c067337 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -52,5 +52,3 @@ jobs: uses: codecov/codecov-action@v3 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - with: - files: ${{steps.coverage.outputs.report}}.lcov From 5d3220361bf60e99c515fc33d5bc8c1dbe84fc01 Mon Sep 17 00:00:00 2001 From: Spencerjibz <=spencernajib2@gmail.com> Date: Fri, 3 Nov 2023 10:06:53 +0000 Subject: [PATCH 16/21] modified grcov settings --- .github/grcov.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/grcov.yml b/.github/grcov.yml index 4c13722..25c42d3 100644 --- a/.github/grcov.yml +++ b/.github/grcov.yml @@ -3,3 +3,5 @@ ignore-not-existing: true llvm: true output-type: lcov output-path: coverage +ignore: + - tests/* From 18d2cc91190a01074bf0a3711ac7df50c820b501 Mon Sep 17 00:00:00 2001 From: Spencerjibz <=spencernajib2@gmail.com> Date: Fri, 3 Nov 2023 10:14:20 +0000 Subject: [PATCH 17/21] Update codecov.yml to specify async-event-emitter test package and args --- .github/workflows/codecov.yml | 2 +- src/lib.rs | 161 ++++++++++++++++++++++++++++++++++ tests/async-event-emitter.rs | 159 --------------------------------- 3 files changed, 162 insertions(+), 160 deletions(-) delete mode 100644 tests/async-event-emitter.rs diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index c067337..9cf03d4 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -31,7 +31,7 @@ jobs: with: command: test - args: --all-features --no-fail-fast + args: --package async-event-emitter -- AsyncEventEmitter --nocapture env: CARGO_INCREMENTAL: "0" RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests" diff --git a/src/lib.rs b/src/lib.rs index 7191810..dcc68de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -366,3 +366,164 @@ impl fmt::Debug for AsyncEventEmitter { .finish() } } + + +#[cfg(test)] + +mod async_event_emitter { + use anyhow::Ok; + use super::AsyncEventEmitter; + use futures::lock::Mutex; + use lazy_static::lazy_static; + use serde::{Deserialize, Serialize}; + + lazy_static! { + // Export the emitter with `pub` keyword + pub static ref EVENT_EMITTER: Mutex = Mutex::new(AsyncEventEmitter::new()); + } + + #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] + struct Date { + month: String, + day: String, + } + #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] + struct Time { + hour: String, + minute: String, + } + #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] + struct DateTime(Date, Time); + + #[tokio::test] + + async fn test_async_event() -> anyhow::Result<()> { + let mut event_emitter = AsyncEventEmitter::new(); + + let date = Date { + month: "January".to_string(), + day: "Tuesday".to_string(), + }; + + event_emitter.on("LOG_DATE", |_date: Date| { + async move { /*Do something here */ } + }); + + event_emitter.on("LOG_DATE", |date: Date| async move { + println!(" emitted data: {:#?}", date) + }); + event_emitter.emit("LOG_DATE", date).await?; + println!("{:#?}", event_emitter); + assert!(event_emitter.listeners.get("LOG_DATE").is_some()); + + Ok(()) + } + + #[tokio::test] + async fn test_emit_multiple_args() -> anyhow::Result<()> { + let mut event_emitter = AsyncEventEmitter::new(); + let name = "LOG_DATE".to_string(); + let payload = ( + Date { + month: "January".to_string(), + day: "Tuesday".to_string(), + }, + name, + ); + + let copy = payload.clone(); + event_emitter.on("LOG_DATE", move |tup: (Date, String)| { + assert_eq!(tup, copy); + async move {} + }); + + event_emitter.emit("LOG_DATE", payload).await?; + + Ok(()) + } + + #[tokio::test] + async fn listens_once_with_multiple_emits() -> anyhow::Result<()> { + let mut event_emitter = AsyncEventEmitter::new(); + let name = "LOG_DATE".to_string(); + event_emitter.once("LOG_DATE", |tup: (Date, String)| async move { + println!("{:#?}", tup) + }); + + event_emitter + .emit( + "LOG_DATE", + ( + Date { + month: "January".to_string(), + day: "Tuesday".to_string(), + }, + name.clone(), + ), + ) + .await?; + event_emitter + .emit( + "LOG_DATE", + ( + Date { + month: "January".to_string(), + day: "Tuesday".to_string(), + }, + name, + ), + ) + .await?; + + assert_eq!(event_emitter.listeners.len(), 1); + if let Some(event) = event_emitter.listeners.get("LOG_DATE") { + println!("{:?}", event) + } + + Ok(()) + } + #[tokio::test] + async fn remove_listeners() -> anyhow::Result<()> { + let mut event_emitter = AsyncEventEmitter::new(); + + let _listener_id = + event_emitter.on( + "PING", + |msg: String| async move { assert_eq!(&msg, "pong") }, + ); + + event_emitter.emit("PING", String::from("pong")).await?; + + event_emitter.remove_listener(&_listener_id); + + if let Some(event_listeners) = event_emitter.listeners.get("PING") { + assert!(event_listeners.is_empty()) + } + + Ok(()) + } + + #[tokio::test] + #[should_panic] + async fn panics_on_different_values_for_same_event() { + let mut event_emitter = AsyncEventEmitter::new(); + + event_emitter.on("value", |_v: Vec| async move {}); + + event_emitter + .emit::<&'static str>("value", "string") + .await + .unwrap(); + event_emitter.emit("value", 12).await.unwrap(); + } + #[tokio::test] + + async fn global_event_emitter() { + // We need to maintain a lock through the mutex so we can avoid data races + EVENT_EMITTER + .lock() + .await + .on("Hello", |v: String| async move { assert_eq!(&v, "world") }); + let _ = EVENT_EMITTER.lock().await.emit("Hello", "world").await; + } +} diff --git a/tests/async-event-emitter.rs b/tests/async-event-emitter.rs deleted file mode 100644 index eb4056a..0000000 --- a/tests/async-event-emitter.rs +++ /dev/null @@ -1,159 +0,0 @@ -#[cfg(test)] - -mod async_event_emitter { - use anyhow::Ok; - use async_event_emitter::AsyncEventEmitter; - use futures::lock::Mutex; - use lazy_static::lazy_static; - use serde::{Deserialize, Serialize}; - - lazy_static! { - // Export the emitter with `pub` keyword - pub static ref EVENT_EMITTER: Mutex = Mutex::new(AsyncEventEmitter::new()); - } - - #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] - struct Date { - month: String, - day: String, - } - #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] - struct Time { - hour: String, - minute: String, - } - #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] - struct DateTime(Date, Time); - - #[tokio::test] - - async fn test_async_event() -> anyhow::Result<()> { - let mut event_emitter = AsyncEventEmitter::new(); - - let date = Date { - month: "January".to_string(), - day: "Tuesday".to_string(), - }; - - event_emitter.on("LOG_DATE", |_date: Date| { - async move { /*Do something here */ } - }); - - event_emitter.on("LOG_DATE", |date: Date| async move { - println!(" emitted data: {:#?}", date) - }); - event_emitter.emit("LOG_DATE", date).await?; - println!("{:#?}", event_emitter); - assert!(event_emitter.listeners.get("LOG_DATE").is_some()); - - Ok(()) - } - - #[tokio::test] - async fn test_emit_multiple_args() -> anyhow::Result<()> { - let mut event_emitter = AsyncEventEmitter::new(); - let name = "LOG_DATE".to_string(); - let payload = ( - Date { - month: "January".to_string(), - day: "Tuesday".to_string(), - }, - name, - ); - - let copy = payload.clone(); - event_emitter.on("LOG_DATE", move |tup: (Date, String)| { - assert_eq!(tup, copy); - async move {} - }); - - event_emitter.emit("LOG_DATE", payload).await?; - - Ok(()) - } - - #[tokio::test] - async fn listens_once_with_multiple_emits() -> anyhow::Result<()> { - let mut event_emitter = AsyncEventEmitter::new(); - let name = "LOG_DATE".to_string(); - event_emitter.once("LOG_DATE", |tup: (Date, String)| async move { - println!("{:#?}", tup) - }); - - event_emitter - .emit( - "LOG_DATE", - ( - Date { - month: "January".to_string(), - day: "Tuesday".to_string(), - }, - name.clone(), - ), - ) - .await?; - event_emitter - .emit( - "LOG_DATE", - ( - Date { - month: "January".to_string(), - day: "Tuesday".to_string(), - }, - name, - ), - ) - .await?; - - assert_eq!(event_emitter.listeners.len(), 1); - if let Some(event) = event_emitter.listeners.get("LOG_DATE") { - println!("{:?}", event) - } - - Ok(()) - } - #[tokio::test] - async fn remove_listeners() -> anyhow::Result<()> { - let mut event_emitter = AsyncEventEmitter::new(); - - let _listener_id = - event_emitter.on( - "PING", - |msg: String| async move { assert_eq!(&msg, "pong") }, - ); - - event_emitter.emit("PING", String::from("pong")).await?; - - event_emitter.remove_listener(&_listener_id); - - if let Some(event_listeners) = event_emitter.listeners.get("PING") { - assert!(event_listeners.is_empty()) - } - - Ok(()) - } - - #[tokio::test] - #[should_panic] - async fn panics_on_different_values_for_same_event() { - let mut event_emitter = AsyncEventEmitter::new(); - - event_emitter.on("value", |_v: Vec| async move {}); - - event_emitter - .emit::<&'static str>("value", "string") - .await - .unwrap(); - event_emitter.emit("value", 12).await.unwrap(); - } - #[tokio::test] - - async fn global_event_emitter() { - // We need to maintain a lock through the mutex so we can avoid data races - EVENT_EMITTER - .lock() - .await - .on("Hello", |v: String| async move { assert_eq!(&v, "world") }); - let _ = EVENT_EMITTER.lock().await.emit("Hello", "world").await; - } -} From bf3e76a79a2e66ce1d6e5474f5860a0320737823 Mon Sep 17 00:00:00 2001 From: Spencerjibz <=spencernajib2@gmail.com> Date: Fri, 3 Nov 2023 10:20:49 +0000 Subject: [PATCH 18/21] Update grcov and codecov configuration and test dependencies in lib.rs --- .github/grcov.yml | 2 -- .github/workflows/codecov.yml | 2 +- src/lib.rs | 3 +-- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/grcov.yml b/.github/grcov.yml index 25c42d3..4c13722 100644 --- a/.github/grcov.yml +++ b/.github/grcov.yml @@ -3,5 +3,3 @@ ignore-not-existing: true llvm: true output-type: lcov output-path: coverage -ignore: - - tests/* diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 9cf03d4..c067337 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -31,7 +31,7 @@ jobs: with: command: test - args: --package async-event-emitter -- AsyncEventEmitter --nocapture + args: --all-features --no-fail-fast env: CARGO_INCREMENTAL: "0" RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests" diff --git a/src/lib.rs b/src/lib.rs index dcc68de..ee50645 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -367,12 +367,11 @@ impl fmt::Debug for AsyncEventEmitter { } } - #[cfg(test)] mod async_event_emitter { - use anyhow::Ok; use super::AsyncEventEmitter; + use anyhow::Ok; use futures::lock::Mutex; use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; From bc4da796d9541252a6bf471c9b2fe3c551c0a720 Mon Sep 17 00:00:00 2001 From: Spencerjibz <=spencernajib2@gmail.com> Date: Fri, 3 Nov 2023 10:27:10 +0000 Subject: [PATCH 19/21] Update output-type and remove llvm flag --- .github/grcov.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/grcov.yml b/.github/grcov.yml index 4c13722..ce25e99 100644 --- a/.github/grcov.yml +++ b/.github/grcov.yml @@ -1,5 +1,5 @@ branch: true ignore-not-existing: true -llvm: true + output-type: lcov output-path: coverage From ef17b7366decec099b79eae57085a675389fa6ab Mon Sep 17 00:00:00 2001 From: Spencerjibz <=spencernajib2@gmail.com> Date: Fri, 3 Nov 2023 11:02:05 +0000 Subject: [PATCH 20/21] Remove unused `Context` import and serialize value directly in emit function --- src/lib.rs | 72 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ee50645..8c8c57d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -113,7 +113,6 @@ License: MIT */ -use anyhow::Context; use serde::{Deserialize, Serialize}; use std::{collections::HashMap, sync::Arc}; use tokio::task::{self}; @@ -169,10 +168,7 @@ impl AsyncEventEmitter { if let Some(listeners) = self.listeners.get_mut(event) { let mut listeners_to_remove: Vec = Vec::new(); for (index, listener) in listeners.iter_mut().enumerate() { - let bytes: Vec = bincode::serialize(&value).context(format!( - " typeof {} can't be serialized", - std::any::type_name::() - ))?; + let bytes: Vec = bincode::serialize(&value)?; let callback = Arc::clone(&listener.callback); @@ -372,7 +368,7 @@ impl fmt::Debug for AsyncEventEmitter { mod async_event_emitter { use super::AsyncEventEmitter; use anyhow::Ok; - use futures::lock::Mutex; + use futures::{lock::Mutex, FutureExt}; use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; @@ -421,6 +417,10 @@ mod async_event_emitter { #[tokio::test] async fn test_emit_multiple_args() -> anyhow::Result<()> { let mut event_emitter = AsyncEventEmitter::new(); + let time = Time { + hour: "22".to_owned(), + minute: "30".to_owned(), + }; let name = "LOG_DATE".to_string(); let payload = ( Date { @@ -428,10 +428,11 @@ mod async_event_emitter { day: "Tuesday".to_string(), }, name, + time, ); let copy = payload.clone(); - event_emitter.on("LOG_DATE", move |tup: (Date, String)| { + event_emitter.on("LOG_DATE", move |tup: (Date, String, Time)| { assert_eq!(tup, copy); async move {} }); @@ -484,6 +485,17 @@ mod async_event_emitter { #[tokio::test] async fn remove_listeners() -> anyhow::Result<()> { let mut event_emitter = AsyncEventEmitter::new(); + let dt = DateTime( + Date { + month: "11".to_owned(), + day: String::from("03"), + }, + Time { + hour: "12".to_owned(), + minute: "50".to_owned(), + }, + ); + let copy = dt.clone(); let _listener_id = event_emitter.on( @@ -491,7 +503,17 @@ mod async_event_emitter { |msg: String| async move { assert_eq!(&msg, "pong") }, ); + let _listener_two = event_emitter.on("DateTime", move |d: Vec| { + let copy = dt.clone(); + async move { + let a = bincode::serialize(©).unwrap(); + assert!(!a.is_empty()); + assert!(!d.is_empty()) + } + }); + event_emitter.emit("PING", String::from("pong")).await?; + event_emitter.emit("DateTime", copy).await?; event_emitter.remove_listener(&_listener_id); @@ -525,4 +547,40 @@ mod async_event_emitter { .on("Hello", |v: String| async move { assert_eq!(&v, "world") }); let _ = EVENT_EMITTER.lock().await.emit("Hello", "world").await; } + + // tests/listener_tests.rs + + use crate::AsyncListener; + use std::sync::Arc; + + #[test] + fn test_async_listener() { + // Test cases for AsyncListener struct + + // Basic test with default values + let listener = AsyncListener { + callback: Arc::new(|_| async {}.boxed()), + limit: None, + id: "1".to_string(), + }; + + assert_eq!(listener.limit, None); + assert_eq!(listener.id.clone(), "1"); + + // Test with custom values + let callback = Arc::new(|_| async {}.boxed()); + let limit = Some(10); + let id = "my-id".to_string(); + + let listener = AsyncListener { + callback, + limit, + id: id.clone(), + }; + + assert_eq!(listener.limit, limit); + assert_eq!(listener.id, id); + + // Add more test cases to cover edge cases + } } From c3e555896ca92ea69913ce682a1cb0175bfcefb2 Mon Sep 17 00:00:00 2001 From: Spencerjibz <=spencernajib2@gmail.com> Date: Fri, 3 Nov 2023 11:15:01 +0000 Subject: [PATCH 21/21] clean up tests --- .github/grcov.yml | 2 + src/lib.rs | 224 +-------------------------------------------- tests/emitter.rs | 225 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 228 insertions(+), 223 deletions(-) create mode 100644 tests/emitter.rs diff --git a/.github/grcov.yml b/.github/grcov.yml index ce25e99..0d3a174 100644 --- a/.github/grcov.yml +++ b/.github/grcov.yml @@ -3,3 +3,5 @@ ignore-not-existing: true output-type: lcov output-path: coverage +ignore: + - /tests/* diff --git a/src/lib.rs b/src/lib.rs index 8c8c57d..a63d228 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -124,7 +124,7 @@ pub type AsyncCB = dyn Fn(Vec) -> BoxFuture<'static, ()> + Send + Sync + 'st #[derive(Clone)] pub struct AsyncListener { - callback: Arc, + pub callback: Arc, pub limit: Option, pub id: String, } @@ -362,225 +362,3 @@ impl fmt::Debug for AsyncEventEmitter { .finish() } } - -#[cfg(test)] - -mod async_event_emitter { - use super::AsyncEventEmitter; - use anyhow::Ok; - use futures::{lock::Mutex, FutureExt}; - use lazy_static::lazy_static; - use serde::{Deserialize, Serialize}; - - lazy_static! { - // Export the emitter with `pub` keyword - pub static ref EVENT_EMITTER: Mutex = Mutex::new(AsyncEventEmitter::new()); - } - - #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] - struct Date { - month: String, - day: String, - } - #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] - struct Time { - hour: String, - minute: String, - } - #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] - struct DateTime(Date, Time); - - #[tokio::test] - - async fn test_async_event() -> anyhow::Result<()> { - let mut event_emitter = AsyncEventEmitter::new(); - - let date = Date { - month: "January".to_string(), - day: "Tuesday".to_string(), - }; - - event_emitter.on("LOG_DATE", |_date: Date| { - async move { /*Do something here */ } - }); - - event_emitter.on("LOG_DATE", |date: Date| async move { - println!(" emitted data: {:#?}", date) - }); - event_emitter.emit("LOG_DATE", date).await?; - println!("{:#?}", event_emitter); - assert!(event_emitter.listeners.get("LOG_DATE").is_some()); - - Ok(()) - } - - #[tokio::test] - async fn test_emit_multiple_args() -> anyhow::Result<()> { - let mut event_emitter = AsyncEventEmitter::new(); - let time = Time { - hour: "22".to_owned(), - minute: "30".to_owned(), - }; - let name = "LOG_DATE".to_string(); - let payload = ( - Date { - month: "January".to_string(), - day: "Tuesday".to_string(), - }, - name, - time, - ); - - let copy = payload.clone(); - event_emitter.on("LOG_DATE", move |tup: (Date, String, Time)| { - assert_eq!(tup, copy); - async move {} - }); - - event_emitter.emit("LOG_DATE", payload).await?; - - Ok(()) - } - - #[tokio::test] - async fn listens_once_with_multiple_emits() -> anyhow::Result<()> { - let mut event_emitter = AsyncEventEmitter::new(); - let name = "LOG_DATE".to_string(); - event_emitter.once("LOG_DATE", |tup: (Date, String)| async move { - println!("{:#?}", tup) - }); - - event_emitter - .emit( - "LOG_DATE", - ( - Date { - month: "January".to_string(), - day: "Tuesday".to_string(), - }, - name.clone(), - ), - ) - .await?; - event_emitter - .emit( - "LOG_DATE", - ( - Date { - month: "January".to_string(), - day: "Tuesday".to_string(), - }, - name, - ), - ) - .await?; - - assert_eq!(event_emitter.listeners.len(), 1); - if let Some(event) = event_emitter.listeners.get("LOG_DATE") { - println!("{:?}", event) - } - - Ok(()) - } - #[tokio::test] - async fn remove_listeners() -> anyhow::Result<()> { - let mut event_emitter = AsyncEventEmitter::new(); - let dt = DateTime( - Date { - month: "11".to_owned(), - day: String::from("03"), - }, - Time { - hour: "12".to_owned(), - minute: "50".to_owned(), - }, - ); - let copy = dt.clone(); - - let _listener_id = - event_emitter.on( - "PING", - |msg: String| async move { assert_eq!(&msg, "pong") }, - ); - - let _listener_two = event_emitter.on("DateTime", move |d: Vec| { - let copy = dt.clone(); - async move { - let a = bincode::serialize(©).unwrap(); - assert!(!a.is_empty()); - assert!(!d.is_empty()) - } - }); - - event_emitter.emit("PING", String::from("pong")).await?; - event_emitter.emit("DateTime", copy).await?; - - event_emitter.remove_listener(&_listener_id); - - if let Some(event_listeners) = event_emitter.listeners.get("PING") { - assert!(event_listeners.is_empty()) - } - - Ok(()) - } - - #[tokio::test] - #[should_panic] - async fn panics_on_different_values_for_same_event() { - let mut event_emitter = AsyncEventEmitter::new(); - - event_emitter.on("value", |_v: Vec| async move {}); - - event_emitter - .emit::<&'static str>("value", "string") - .await - .unwrap(); - event_emitter.emit("value", 12).await.unwrap(); - } - #[tokio::test] - - async fn global_event_emitter() { - // We need to maintain a lock through the mutex so we can avoid data races - EVENT_EMITTER - .lock() - .await - .on("Hello", |v: String| async move { assert_eq!(&v, "world") }); - let _ = EVENT_EMITTER.lock().await.emit("Hello", "world").await; - } - - // tests/listener_tests.rs - - use crate::AsyncListener; - use std::sync::Arc; - - #[test] - fn test_async_listener() { - // Test cases for AsyncListener struct - - // Basic test with default values - let listener = AsyncListener { - callback: Arc::new(|_| async {}.boxed()), - limit: None, - id: "1".to_string(), - }; - - assert_eq!(listener.limit, None); - assert_eq!(listener.id.clone(), "1"); - - // Test with custom values - let callback = Arc::new(|_| async {}.boxed()); - let limit = Some(10); - let id = "my-id".to_string(); - - let listener = AsyncListener { - callback, - limit, - id: id.clone(), - }; - - assert_eq!(listener.limit, limit); - assert_eq!(listener.id, id); - - // Add more test cases to cover edge cases - } -} diff --git a/tests/emitter.rs b/tests/emitter.rs new file mode 100644 index 0000000..23290c9 --- /dev/null +++ b/tests/emitter.rs @@ -0,0 +1,225 @@ +#[cfg(test)] + +mod async_event_emitter { + use anyhow::Ok; + use async_event_emitter::AsyncEventEmitter; + use futures::{lock::Mutex, FutureExt}; + use lazy_static::lazy_static; + use serde::{Deserialize, Serialize}; + use std::sync::Arc; + + lazy_static! { + // Export the emitter with `pub` keyword + pub static ref EVENT_EMITTER: Mutex = Mutex::new(AsyncEventEmitter::new()); + } + + #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] + struct Date { + month: String, + day: String, + } + #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] + struct Time { + hour: String, + minute: String, + } + #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] + struct DateTime(Date, Time); + + #[tokio::test] + + async fn test_async_event() -> anyhow::Result<()> { + let mut event_emitter = AsyncEventEmitter::new(); + + let date = Date { + month: "January".to_string(), + day: "Tuesday".to_string(), + }; + + event_emitter.on("LOG_DATE", |_date: Date| { + async move { /*Do something here */ } + }); + + event_emitter.on("LOG_DATE", |date: Date| async move { + println!(" emitted data: {:#?}", date) + }); + event_emitter.emit("LOG_DATE", date).await?; + println!("{:#?}", event_emitter); + assert!(event_emitter.listeners.get("LOG_DATE").is_some()); + + Ok(()) + } + + #[tokio::test] + async fn test_emit_multiple_args() -> anyhow::Result<()> { + let mut event_emitter = AsyncEventEmitter::new(); + let time = Time { + hour: "22".to_owned(), + minute: "30".to_owned(), + }; + let name = "LOG_DATE".to_string(); + let payload = ( + Date { + month: "January".to_string(), + day: "Tuesday".to_string(), + }, + name, + time, + ); + + let copy = payload.clone(); + event_emitter.on("LOG_DATE", move |tup: (Date, String, Time)| { + assert_eq!(tup, copy); + async move {} + }); + + event_emitter.emit("LOG_DATE", payload).await?; + + Ok(()) + } + + #[tokio::test] + async fn listens_once_with_multiple_emits() -> anyhow::Result<()> { + let mut event_emitter = AsyncEventEmitter::new(); + let name = "LOG_DATE".to_string(); + event_emitter.once("LOG_DATE", |tup: (Date, String)| async move { + println!("{:#?}", tup) + }); + + event_emitter + .emit( + "LOG_DATE", + ( + Date { + month: "January".to_string(), + day: "Tuesday".to_string(), + }, + name.clone(), + ), + ) + .await?; + event_emitter + .emit( + "LOG_DATE", + ( + Date { + month: "January".to_string(), + day: "Tuesday".to_string(), + }, + name, + ), + ) + .await?; + + assert_eq!(event_emitter.listeners.len(), 1); + if let Some(event) = event_emitter.listeners.get("LOG_DATE") { + println!("{:?}", event) + } + + Ok(()) + } + #[tokio::test] + async fn remove_listeners() -> anyhow::Result<()> { + let mut event_emitter = AsyncEventEmitter::new(); + let dt = DateTime( + Date { + month: "11".to_owned(), + day: String::from("03"), + }, + Time { + hour: "12".to_owned(), + minute: "50".to_owned(), + }, + ); + let copy = dt.clone(); + + let _listener_id = + event_emitter.on( + "PING", + |msg: String| async move { assert_eq!(&msg, "pong") }, + ); + + let _listener_two = event_emitter.on("DateTime", move |d: Vec| { + let copy = dt.clone(); + async move { + let a = bincode::serialize(©).unwrap(); + assert!(!a.is_empty()); + assert!(!d.is_empty()) + } + }); + + event_emitter.emit("PING", String::from("pong")).await?; + event_emitter.emit("DateTime", copy).await?; + + if let Some(id) = event_emitter.remove_listener(&_listener_id) { + assert_eq!(id, _listener_id) + } + + if let Some(event_listeners) = event_emitter.listeners.get("PING") { + assert!(event_listeners.is_empty()) + } + assert!(event_emitter.remove_listener("some").is_none()); + + Ok(()) + } + + #[tokio::test] + #[should_panic] + async fn panics_on_different_values_for_same_event() { + let mut event_emitter = AsyncEventEmitter::new(); + + event_emitter.on("value", |_v: Vec| async move {}); + + event_emitter + .emit::<&'static str>("value", "string") + .await + .unwrap(); + event_emitter.emit("value", 12).await.unwrap(); + } + #[tokio::test] + + async fn global_event_emitter() { + // We need to maintain a lock through the mutex so we can avoid data races + EVENT_EMITTER + .lock() + .await + .on("Hello", |v: String| async move { assert_eq!(&v, "world") }); + let _ = EVENT_EMITTER.lock().await.emit("Hello", "world").await; + } + + // tests/listener_tests.rs + + use async_event_emitter::AsyncListener; + + #[test] + fn test_async_listener() { + // Test cases for AsyncListener struct + + // Basic test with default values + let listener = AsyncListener { + callback: Arc::new(|_| async {}.boxed()), + limit: None, + id: "1".to_string(), + }; + + assert_eq!(listener.limit, None); + assert_eq!(listener.id.clone(), "1"); + + // Test with custom values + let callback = Arc::new(|_| async {}.boxed()); + let limit = Some(10); + let id = "my-id".to_string(); + + let listener = AsyncListener { + callback, + limit, + id: id.clone(), + }; + + assert_eq!(listener.limit, limit); + assert_eq!(listener.id, id); + println!("{listener:?}") + + // Add more test cases to cover edge cases + } +}