From 61c53960133d1b6b5ec5d38a6f33c9c85296f179 Mon Sep 17 00:00:00 2001 From: giangndm <45644921+giangndm@users.noreply.github.com> Date: Fri, 20 Dec 2024 16:54:13 +0700 Subject: [PATCH] chore: add github actions (#11) --- .github/workflows/clippy.yml | 63 ++++++++++ .github/workflows/release-plz.yml | 27 +++++ .github/workflows/release.yml | 189 ++++++++++++++++++++++++++++++ .github/workflows/rust-fmt.yml | 36 ++++++ .github/workflows/rust.yml | 85 ++++++++++++++ .github/workflows/typos.yml | 20 ++++ Dockerfile | 21 ++++ deny.toml | 63 ++++++++++ src/emqx_webhook/webhook_types.rs | 5 +- src/http.rs | 2 +- src/hub.rs | 6 +- src/hub/registry.rs | 28 ++--- 12 files changed, 523 insertions(+), 22 deletions(-) create mode 100644 .github/workflows/clippy.yml create mode 100644 .github/workflows/release-plz.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/rust-fmt.yml create mode 100644 .github/workflows/rust.yml create mode 100644 .github/workflows/typos.yml create mode 100644 Dockerfile create mode 100644 deny.toml diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml new file mode 100644 index 0000000..f7e402b --- /dev/null +++ b/.github/workflows/clippy.yml @@ -0,0 +1,63 @@ +# rust-clippy is a tool that runs a bunch of lints to catch common +# mistakes in your Rust code and help improve your Rust code. +# More details at https://github.com/rust-lang/rust-clippy +# and https://rust-lang.github.io/rust-clippy/ + +name: rust-clippy analyze + +on: + push: + branches: ["master"] + pull_request: + branches: ["master"] + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + CARGO_TERM_COLOR: always + +jobs: + rust-clippy-analyze: + name: Run rust-clippy analyzing + runs-on: ubuntu-latest + permissions: + contents: read + security-events: write + actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - uses: actions/cache@v3 + id: cache-cargo + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + restore-keys: ${{ runner.os }}-cargo- + + - name: Install Protoc + uses: arduino/setup-protoc@v3 + with: + version: "25.1" + repo-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Run rust-clippy + run: cargo clippy --all-targets --all-features -- -D warnings + + - name: Install required cargo + run: cargo install clippy-sarif sarif-fmt + + - name: Run rust-sarif + run: cargo clippy --all-features --message-format=json | + clippy-sarif | tee rust-clippy-results.sarif | sarif-fmt + + - name: Upload analysis results to GitHub + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: rust-clippy-results.sarif + wait-for-processing: true \ No newline at end of file diff --git a/.github/workflows/release-plz.yml b/.github/workflows/release-plz.yml new file mode 100644 index 0000000..b313669 --- /dev/null +++ b/.github/workflows/release-plz.yml @@ -0,0 +1,27 @@ +name: Release-plz + +permissions: + pull-requests: write + contents: write + +on: + push: + branches: + - master + +jobs: + release-plz: + name: Release-plz + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + - name: Run release-plz + uses: MarcoIeni/release-plz-action@v0.5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..bbb502e --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,189 @@ +name: Release +on: + push: + branches: [master] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + APP_NAME: atm0s-mqtt + ARTIFACT_DIR: release-builds + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-release: + name: build-release + runs-on: ${{ matrix.os }} + env: + RUST_BACKTRACE: 1 + + strategy: + matrix: + build: + - linux gnu x64 + # - linux musl x64 + - linux gnu aarch64 + # - linux musl aarch64 + # - linux gnueabihf arm + # - linux gnueabihf armv7 + # - linux gnu mips + # - linux gnuabi64 mips64 + # - linux gnuabi64 mips64el + # - linux gnu mipsel + - macos x64 + - macos aarch64 + # - windows gnu x64 + # - windows msvc x64 + include: + - build: linux gnu x64 + os: ubuntu-latest + target: x86_64-unknown-linux-gnu + extension: "" + # - build: linux musl x64 + # os: ubuntu-latest + # target: x86_64-unknown-linux-musl + # extension: "" + - build: linux gnu aarch64 + os: ubuntu-latest + target: aarch64-unknown-linux-gnu + extension: "" + # - build: linux musl aarch64 + # os: ubuntu-latest + # target: aarch64-unknown-linux-musl + # extension: "" + # - build: linux gnueabihf arm + # os: ubuntu-latest + # target: arm-unknown-linux-gnueabihf + # extension: "" + # - build: linux gnueabihf armv7 + # os: ubuntu-latest + # target: armv7-unknown-linux-gnueabihf + # extension: "" + # - build: linux gnu mips + # os: ubuntu-latest + # rust: 1.71.1 + # target: mips-unknown-linux-gnu + # extension: "" + # - build: linux gnuabi64 mips64 + # os: ubuntu-latest + # rust: 1.71.1 + # target: mips64-unknown-linux-gnuabi64 + # extension: "" + # - build: linux gnuabi64 mips64el + # os: ubuntu-latest + # rust: 1.71.1 + # target: mips64el-unknown-linux-gnuabi64 + # extension: "" + # - build: linux gnu mipsel + # os: ubuntu-latest + # rust: 1.71.1 + # target: mipsel-unknown-linux-gnu + # extension: "" + # - build: linux musl aarch64 + # os: ubuntu-latest + # target: aarch64-unknown-linux-musl + # extension: "" + - build: macos x64 + os: macos-latest + target: x86_64-apple-darwin + extension: "" + - build: macos aarch64 + os: macos-latest + target: aarch64-apple-darwin + extension: "" + # - build: windows gnu x64 + # os: ubuntu-latest + # target: x86_64-pc-windows-gnu + # extension: ".exe" + # - build: windows msvc x64 + # os: windows-latest + # target: x86_64-pc-windows-msvc + # extension: ".exe" + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Build binary + uses: houseabsolute/actions-rust-cross@v0 + with: + target: ${{ matrix.target }} + args: "--locked --release" + strip: true + + - name: Upload Artifact to Summary + if: ${{ matrix.build != 'windows gnu x64' && matrix.build != 'windows msvc x64' }} + uses: actions/upload-artifact@v4 + with: + name: ${{ env.APP_NAME }}-${{ matrix.target }}${{ matrix.extension }} + path: | + target/${{ matrix.target }}/release/${{ env.APP_NAME }}${{ matrix.extension }} + + - name: Upload server binarie to release + if: startsWith(github.ref, 'refs/tags/') + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: target/${{ matrix.target }}/release/${{ env.APP_NAME }}${{ matrix.extension }} + asset_name: ${{ env.APP_NAME }}-${{ matrix.target }}${{ matrix.extension }} + tag: ${{ github.ref }} + overwrite: true + + create-release: + # only run if not a tags build + if: startsWith(github.ref, 'refs/tags/') == false + needs: build-release + runs-on: ubuntu-latest + steps: + - uses: actions/download-artifact@v4 + - name: Display structure of downloaded files + run: ls -R + - name: create_release + id: create_release + uses: marvinpinto/action-automatic-releases@latest + with: + repo_token: "${{ secrets.GITHUB_TOKEN }}" + automatic_release_tag: ${{ github.event_name == 'workflow_dispatch' && 'latest' || (github.ref == 'refs/heads/master' && 'latest') || github.ref }} + title: Build ${{ github.event_name == 'workflow_dispatch' && 'development' || github.ref }} + files: | + */* + prerelease: true + + deploy-docker: + needs: build-release + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - uses: actions/download-artifact@v4 + # Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here. + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + # This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels. + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + # This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages. + # It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository. + # It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step. + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + push: true + platforms: linux/amd64,linux/arm64 + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file diff --git a/.github/workflows/rust-fmt.yml b/.github/workflows/rust-fmt.yml new file mode 100644 index 0000000..5687bf6 --- /dev/null +++ b/.github/workflows/rust-fmt.yml @@ -0,0 +1,36 @@ +name: rust-fmt analyze + +on: + push: + branches: ["master"] + pull_request: + branches: ["master"] + +concurrency: + # One build per PR, branch or tag + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + CARGO_TERM_COLOR: always + +jobs: + rust-fmt-analyze: + name: Run rust-fmt analyzing + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - 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') }} + + - name: cargo fmt + run: cargo fmt --all -- --check \ No newline at end of file diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 0000000..2a01ffa --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,85 @@ +name: Rust + +on: + push: + branches: ["master"] + paths-ignore: + - "docs/**" + + pull_request: + branches: ["master"] + paths-ignore: + - "docs/**" + +env: + CARGO_TERM_COLOR: always + +jobs: + code-coverage: + runs-on: ubuntu-latest + env: + CARGO_TERM_COLOR: always + steps: + - uses: actions/checkout@v4 + - name: Install deps + run: | + sudo apt-get update + sudo apt install -y libsoxr-dev libopus-dev libssl-dev libfdk-aac-dev + + - 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') }} + + - name: Install Protoc + uses: arduino/setup-protoc@v3 + with: + version: "25.1" + repo-token: ${{ secrets.GITHUB_TOKEN }} + - name: Install cargo-llvm-cov + uses: taiki-e/install-action@cargo-llvm-cov + - name: Running cargo test + run: cargo test --all-features --workspace + - name: Generate code coverage + run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4 + with: + files: lcov.info + fail_ci_if_error: false + cargo-deny: + name: cargo-deny + + # TODO: remove this matrix when https://github.com/EmbarkStudios/cargo-deny/issues/324 is resolved + strategy: + fail-fast: false + matrix: + platform: + - x86_64-unknown-linux-gnu + # - x86_64-unknown-linux-musl + - aarch64-unknown-linux-gnu + # - arm-unknown-linux-gnueabihf + # - armv7-unknown-linux-gnueabihf + # - mips-unknown-linux-gnu + # - mips64-unknown-linux-gnuabi64 + # - mips64el-unknown-linux-gnuabi64 + # - mipsel-unknown-linux-gnu + # - aarch64-unknown-linux-musl + - x86_64-apple-darwin + - aarch64-apple-darwin + # - x86_64-pc-windows-gnu + # - x86_64-pc-windows-msvc + + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: EmbarkStudios/cargo-deny-action@v1 + with: + command: check + log-level: error + arguments: --all-features --target ${{ matrix.platform }} \ No newline at end of file diff --git a/.github/workflows/typos.yml b/.github/workflows/typos.yml new file mode 100644 index 0000000..f94ca8d --- /dev/null +++ b/.github/workflows/typos.yml @@ -0,0 +1,20 @@ +name: Typos + +on: + push: + branches: ["master"] + pull_request: + branches: ["master"] + +env: + CARGO_TERM_COLOR: always + +jobs: + typos: + runs-on: ubuntu-latest + env: + CARGO_TERM_COLOR: always + steps: + - uses: actions/checkout@v4 + - name: Check spelling issues + uses: crate-ci/typos@master \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d6703a0 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +FROM ubuntu:22.04 as base +ARG TARGETPLATFORM +COPY . /tmp +WORKDIR /tmp + +RUN echo $TARGETPLATFORM +RUN ls -R /tmp/ +# move the binary to root based on platform +RUN case $TARGETPLATFORM in \ + "linux/amd64") BUILD=x86_64-unknown-linux-gnu ;; \ + "linux/arm64") BUILD=aarch64-unknown-linux-gnu ;; \ + *) exit 1 ;; \ + esac; \ + mv /tmp/atm0s-mqtt-$BUILD/atm0s-mqtt /atm0s-mqtt; \ + chmod +x /atm0s-mqtt + +FROM ubuntu:22.04 + +COPY --from=base /atm0s-mqtt /atm0s-mqtt + +ENTRYPOINT ["/atm0s-mqtt"] \ No newline at end of file diff --git a/deny.toml b/deny.toml new file mode 100644 index 0000000..49ce9e2 --- /dev/null +++ b/deny.toml @@ -0,0 +1,63 @@ +# https://github.com/EmbarkStudios/cargo-deny +# +# cargo-deny checks our dependency tree for copy-left licenses, +# duplicate dependencies, and rustsec advisories (https://rustsec.org/advisories). +# +# Install: `cargo install cargo-deny` +# Check: `cargo deny check` or run `cargo_deny.sh`. + +# Note: running just `cargo deny check` without a `--target` can result in +# false positives due to https://github.com/EmbarkStudios/cargo-deny/issues/324 +targets = [ + { triple = "x86_64-unknown-linux-gnu" }, + { triple = "x86_64-unknown-linux-musl" }, + { triple = "aarch64-unknown-linux-gnu" }, + { triple = "arm-unknown-linux-gnueabihf" }, + { triple = "armv7-unknown-linux-gnueabihf" }, + { triple = "mips-unknown-linux-gnu" }, + { triple = "mips64-unknown-linux-gnuabi64" }, + { triple = "mips64el-unknown-linux-gnuabi64" }, + { triple = "mipsel-unknown-linux-gnu" }, + { triple = "aarch64-unknown-linux-musl" }, + { triple = "x86_64-apple-darwin" }, + { triple = "aarch64-apple-darwin" }, + { triple = "x86_64-pc-windows-gnu" }, + { triple = "x86_64-pc-windows-msvc" } +] + +[advisories] +vulnerability = "deny" +unmaintained = "warn" +yanked = "deny" +ignore = [ +] + +[bans] +multiple-versions = "allow" +wildcards = "allow" # at least until https://github.com/EmbarkStudios/cargo-deny/issues/241 is fixed +deny = [] + +skip = [] +skip-tree = [] + + +[licenses] +private = { ignore = true } +unlicensed = "allow" +allow-osi-fsf-free = "neither" +confidence-threshold = 0.92 # We want really high confidence when inferring licenses from text +copyleft = "deny" +allow = [ + "Apache-2.0 WITH LLVM-exception", # https://spdx.org/licenses/LLVM-exception.html + "Apache-2.0", # https://tldrlegal.com/license/apache-license-2.0-(apache-2.0) + "BSD-2-Clause", # https://tldrlegal.com/license/bsd-2-clause-license-(freebsd) + "BSD-3-Clause", # https://tldrlegal.com/license/bsd-3-clause-license-(revised) + "BSL-1.0", # https://tldrlegal.com/license/boost-software-license-1.0-explained + "CC0-1.0", # https://creativecommons.org/publicdomain/zero/1.0/ + "ISC", # https://tldrlegal.com/license/-isc-license + "MIT-0", # https://choosealicense.com/licenses/mit-0/ + "MIT", # https://tldrlegal.com/license/mit-license + "OpenSSL", # https://www.openssl.org/source/license.html - used on Linux + "Unicode-3.0", # https://spdx.org/licenses/Unicode-3.0.html + "Zlib", # https://tldrlegal.com/license/zlib-libpng-license-(zlib) +] \ No newline at end of file diff --git a/src/emqx_webhook/webhook_types.rs b/src/emqx_webhook/webhook_types.rs index 3abface..ce0f495 100644 --- a/src/emqx_webhook/webhook_types.rs +++ b/src/emqx_webhook/webhook_types.rs @@ -18,10 +18,7 @@ pub enum ValidateResult { impl ValidateResult { pub fn is_allow(&self) -> bool { - match self { - ValidateResult::Allow => true, - _ => false, - } + matches!(self, ValidateResult::Allow) } } diff --git a/src/http.rs b/src/http.rs index eac9610..8acfdf3 100644 --- a/src/http.rs +++ b/src/http.rs @@ -29,7 +29,7 @@ pub fn run_http(listen: SocketAddr) -> Receiver { let (cmd_tx, cmd_rx) = channel(10); tokio::spawn(async move { - let emqx_route = emqx::route(cmd_tx).with(Cors::new()).with(Tracing::default()); + let emqx_route = emqx::route(cmd_tx).with(Cors::new()).with(Tracing); Server::new(TcpListener::bind(listen)).run(Route::new().nest("/api", emqx_route)).await }); diff --git a/src/hub.rs b/src/hub.rs index 4b02041..3ce4b15 100644 --- a/src/hub.rs +++ b/src/hub.rs @@ -65,7 +65,7 @@ impl Hub { for leg_id in self.local_registry.get(&topic).into_iter().flatten() { has_subscribers = true; log::info!("[Hub] publish {topic_str} to local leg {leg_id:?}"); - let event_tx = self.legs.get(&leg_id).expect("should have leg with leg_id"); + let event_tx = self.legs.get(leg_id).expect("should have leg with leg_id"); let _ = event_tx.send(LegOutput::Publish(pkt.clone())); } let dests = self.remote_registry.get(&topic).into_iter().flatten().cloned().collect::>(); @@ -120,10 +120,10 @@ impl Hub { P2pServiceEvent::Unicast(peer_id, vec) => { if let Ok(pkt) = PublishPacket::decode(&mut vec.as_slice()) { let topic_str: &str = pkt.topic_name(); - if let Ok(topic) = Topic::from_str(&topic_str) { + if let Ok(topic) = Topic::from_str(topic_str) { for leg_id in self.local_registry.get(&topic).into_iter().flatten() { log::info!("[Hub] forward {topic_str} to local leg {leg_id:?} from remote {peer_id:?}"); - let event_tx = self.legs.get(&leg_id).expect("should have leg with leg_id"); + let event_tx = self.legs.get(leg_id).expect("should have leg with leg_id"); let _ = event_tx.send(LegOutput::Publish(pkt.clone())); } } diff --git a/src/hub/registry.rs b/src/hub/registry.rs index 848dafa..12d39e1 100644 --- a/src/hub/registry.rs +++ b/src/hub/registry.rs @@ -117,7 +117,7 @@ where pub fn subscribe(&mut self, parts: &[TopicPart], target: T) -> Option { if let Some(next) = parts.first() { if let Some(child) = self.children.get_mut(next) { - return child.subscribe(&parts[1..], target); + child.subscribe(&parts[1..], target) } else { let mut node = Box::new(RegistryNode::default()); node.subscribe(&parts[1..], target); @@ -125,7 +125,7 @@ where Some(SubscribeResult::NodeAdded) } } else { - self.targets.insert(target).then(|| SubscribeResult::TargetAdded) + self.targets.insert(target).then_some(SubscribeResult::TargetAdded) } } @@ -143,7 +143,7 @@ where None } } else { - self.targets.remove(&target).then(|| UnsubscribeResult::TargetRemoved) + self.targets.remove(&target).then_some(UnsubscribeResult::TargetRemoved) } } @@ -152,15 +152,15 @@ where match next { TopicPart::SingleWildcard | TopicPart::MultiWildcard => None, TopicPart::Value(_) => { - let exact_child = self.children.get(next).map(|c| c.get(&parts[1..], dest)).flatten(); - let single_wildcard_child = self.children.get(&TopicPart::SingleWildcard).map(|c| c.get(&parts[1..], dest)).flatten(); - let multi_wildcard_child = self.children.get(&TopicPart::MultiWildcard).map(|c| c.get(&[], dest)).flatten(); + let exact_child = self.children.get(next).and_then(|c| c.get(&parts[1..], dest)); + let single_wildcard_child = self.children.get(&TopicPart::SingleWildcard).and_then(|c| c.get(&parts[1..], dest)); + let multi_wildcard_child = self.children.get(&TopicPart::MultiWildcard).and_then(|c| c.get(&[], dest)); exact_child.or(single_wildcard_child).or(multi_wildcard_child) } } } else { - dest.extend(self.targets.iter().map(|t| t.clone())); + dest.extend(self.targets.iter().cloned()); Some(()) } } @@ -218,7 +218,7 @@ mod tests { assert_eq!(registry.unsubscribe(&Topic::from_str("a").expect("should parse topic"), 1), None); assert_eq!(get_vec(&mut registry, "a"), None); - assert_eq!(registry.is_empty(), true); + assert!(registry.is_empty()); } #[test] @@ -238,7 +238,7 @@ mod tests { assert_eq!(registry.unsubscribe(&Topic::from_str("a/b/c").expect("should parse topic"), 3), Some(UnsubscribeResult::NodeRemoved)); assert_eq!(get_vec(&mut registry, "a/b/c"), None); - assert_eq!(registry.is_empty(), true); + assert!(registry.is_empty()); } #[test] @@ -256,7 +256,7 @@ mod tests { assert_eq!(get_vec(&mut registry, "a/a/c"), None); assert_eq!(get_vec(&mut registry, "b/a/c"), None); - assert_eq!(registry.is_empty(), true); + assert!(registry.is_empty()); } #[test] @@ -274,7 +274,7 @@ mod tests { assert_eq!(get_vec(&mut registry, "w/b/c"), None); assert_eq!(get_vec(&mut registry, "w/f/c"), None); - assert_eq!(registry.is_empty(), true); + assert!(registry.is_empty()); } #[test] @@ -292,7 +292,7 @@ mod tests { assert_eq!(get_vec(&mut registry, "a/b/w"), None); assert_eq!(get_vec(&mut registry, "a/b/w/z"), None); - assert_eq!(registry.is_empty(), true); + assert!(registry.is_empty()); } #[test] @@ -311,7 +311,7 @@ mod tests { assert_eq!(get_vec(&mut registry, "a/b/c/d"), None); assert_eq!(get_vec(&mut registry, "a/b/c/d/e"), None); - assert_eq!(registry.is_empty(), true); + assert!(registry.is_empty()); } #[test] @@ -330,6 +330,6 @@ mod tests { assert_eq!(get_vec(&mut registry, "a/b/c/d"), None); assert_eq!(get_vec(&mut registry, "a/c/c/d/e"), None); - assert_eq!(registry.is_empty(), true); + assert!(registry.is_empty()); } }