diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e889dd9..5b1b44b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,10 +46,13 @@ jobs: - name: check clippy if: ${{ matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' }} run: cargo clippy --all --all-targets -- -D clippy::all && cargo clippy --no-default-features --features prost-codec --features std -- -D clippy::all - - name: check no_std compatibility + - name: install targets + run: rustup target add x86_64-unknown-none + - name: run build for no-std target + # No-std implementation uses feature that can only be compiled by nightly version + if: ${{ matrix.rust == 'nightly' }} run: cargo build --no-default-features --features prost-codec --target x86_64-unknown-none - name: run tests with no-std enabled - # No-std implementation uses feature that can only be compiled by nightly version if: ${{ matrix.rust == 'nightly' }} run: cargo test --all --no-default-features --features=prost-codec --features=default-logger --no-fail-fast -- --nocapture - run: cargo test --all --no-fail-fast -- --nocapture diff --git a/Cargo.toml b/Cargo.toml index 8c0311a..bdd61d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ ahash = { version = "0.8.3", default-features = false } fail = { version = "0.4", optional = true } getset = "0.1.1" protobuf = { version = "2", optional = true } -prost = { version = "0.11", optional = true, default-features = false, features = ["prost-derive"] } +prost = { version = "0.12.4", optional = true, default-features = false, features = ["prost-derive"] } thiserror = { version = "1.0", optional = true } raft-proto = { path = "proto", version = "0.7.0", default-features = false } rand = { version = "0.8", default-features = false, features = ["alloc", "small_rng", "getrandom"] } diff --git a/examples/single_mem_node/main.rs b/examples/single_mem_node/main.rs index 8ef7c57..c60637f 100644 --- a/examples/single_mem_node/main.rs +++ b/examples/single_mem_node/main.rs @@ -6,7 +6,6 @@ use std::sync::mpsc::{self, RecvTimeoutError}; use std::thread; use std::time::{Duration, Instant}; -use raft::eraftpb::ConfState; use raft::prelude::*; use raft::storage::MemStorage; diff --git a/harness/tests/integration_cases/mod.rs b/harness/tests/integration_cases/mod.rs index 5e3928f..3ff5322 100644 --- a/harness/tests/integration_cases/mod.rs +++ b/harness/tests/integration_cases/mod.rs @@ -1,5 +1,5 @@ // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. - +#[allow(clippy::all)] mod test_raft; mod test_raft_flow_control; mod test_raft_paper; diff --git a/harness/tests/integration_cases/test_raft.rs b/harness/tests/integration_cases/test_raft.rs index 427e364..485e192 100644 --- a/harness/tests/integration_cases/test_raft.rs +++ b/harness/tests/integration_cases/test_raft.rs @@ -22,7 +22,7 @@ use harness::*; #[cfg(feature = "protobuf-codec")] use protobuf::Message as PbMessage; use raft::eraftpb::*; -use raft::storage::{GetEntriesContext, MemStorage}; +use raft::storage::MemStorage; use raft::*; use raft_proto::*; use slog::Logger; diff --git a/harness/tests/integration_cases/test_raw_node.rs b/harness/tests/integration_cases/test_raw_node.rs index a33d0ca..a0f5d2d 100644 --- a/harness/tests/integration_cases/test_raw_node.rs +++ b/harness/tests/integration_cases/test_raw_node.rs @@ -18,7 +18,7 @@ use harness::Network; #[cfg(feature = "protobuf-codec")] use protobuf::{Message as PbMessage, ProtobufEnum as _}; use raft::eraftpb::*; -use raft::storage::{GetEntriesContext, MemStorage}; +use raft::storage::MemStorage; use raft::*; use raft_proto::*; use slog::Logger; @@ -174,6 +174,11 @@ fn test_raw_node_read_index_to_old_leader() { ); } +fn sort_conf_state_collections(cs: &mut ConfState) { + cs.voters.sort(); + cs.learners.sort(); +} + /// Tests the configuration change mechanism. Each test case sends a configuration /// change which is either simple or joint, verifies that it applies and that the /// resulting ConfState matches expectations, and for joint configurations makes @@ -251,7 +256,7 @@ fn test_raw_node_propose_and_conf_change() { let cs = conf_state_v2(vec![2], vec![3], vec![1], vec![1], true); test_cases.push((Box::new(cc), cs, Some(conf_state(vec![2], vec![1, 3])))); - for (cc, exp, exp2) in test_cases { + for (cc, mut exp, exp2) in test_cases { let s = new_storage(); let mut raw_node = new_raw_node(1, vec![1], 10, 1, s.clone(), &l); raw_node.campaign().unwrap(); @@ -321,7 +326,10 @@ fn test_raw_node_propose_and_conf_change() { assert_eq!(entries[1].get_entry_type(), EntryType::EntryConfChangeV2); } assert_eq!(ccdata, entries[1].get_data()); - assert_eq!(exp, cs.unwrap()); + let mut cs = cs.unwrap(); + sort_conf_state_collections(&mut cs); + sort_conf_state_collections(&mut exp); + assert_eq!(exp, cs); let conf_index = if cc.as_v2().enter_joint() == Some(true) { // If this is an auto-leaving joint conf change, it will have @@ -366,8 +374,11 @@ fn test_raw_node_propose_and_conf_change() { assert_eq!(context, leave_cc.get_context(), "{:?}", cc.as_v2()); // Lie and pretend the ConfChange applied. It won't do so because now // we require the joint quorum and we're only running one node. - let cs = raw_node.apply_conf_change(&leave_cc).unwrap(); - assert_eq!(cs, exp2.unwrap()); + let mut cs = raw_node.apply_conf_change(&leave_cc).unwrap(); + let mut exp2 = exp2.unwrap(); + sort_conf_state_collections(&mut cs); + sort_conf_state_collections(&mut exp2); + assert_eq!(cs, exp2); } } diff --git a/proto/Cargo.toml b/proto/Cargo.toml index eca6daf..a3049aa 100644 --- a/proto/Cargo.toml +++ b/proto/Cargo.toml @@ -24,5 +24,5 @@ protobuf-build = { version = "0.15.1", default-features = false } [dependencies] bytes = { version = "1", optional = true, default-features = false } lazy_static = { version = "1", optional = true, default-features = false, features = ["spin_no_std"] } -prost = { version = "0.11", optional = true, default-features = false, features = ["prost-derive"] } +prost = { version = "0.12.4", optional = true, default-features = false, features = ["prost-derive"] } protobuf = { version = "2", optional = true } diff --git a/proto/src/confchange.rs b/proto/src/confchange.rs index ca792bc..5e67656 100644 --- a/proto/src/confchange.rs +++ b/proto/src/confchange.rs @@ -1,5 +1,5 @@ // Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0. - +#![allow(unused_imports)] extern crate alloc; use crate::eraftpb::{ @@ -11,11 +11,6 @@ use alloc::string::String; use alloc::vec; use alloc::vec::Vec; use core::fmt::Write; -use core::iter::Iterator; -use core::option::Option; -use core::option::Option::{None, Some}; -use core::result::Result; -use core::result::Result::{Err, Ok}; use core::write; /// Creates a `ConfChangeSingle`. diff --git a/proto/src/lib.rs b/proto/src/lib.rs index 1ba118f..a9ec60b 100644 --- a/proto/src/lib.rs +++ b/proto/src/lib.rs @@ -55,8 +55,6 @@ pub mod prelude { pub mod util { use crate::eraftpb::ConfState; - use core::convert::From; - use core::iter::IntoIterator; impl From<(Iter1, Iter2)> for ConfState where diff --git a/proto/src/wrappers.rs b/proto/src/wrappers.rs index aa338c1..77cb80f 100644 --- a/proto/src/wrappers.rs +++ b/proto/src/wrappers.rs @@ -1,5 +1,6 @@ // Generated file, modified and added to support no_std +#[allow(deprecated)] impl Entry { #[inline] pub fn default_ref() -> &'static Self { @@ -220,6 +221,7 @@ impl Snapshot { .unwrap_or_else(SnapshotMetadata::default) } } +#[allow(deprecated)] impl Message { pub fn new() -> Self { Self::default() @@ -604,6 +606,7 @@ impl ConfState { self.auto_leave } } +#[allow(deprecated)] impl ConfChange { pub fn write_to_bytes( &self, @@ -683,6 +686,7 @@ impl ConfChange { self.id } } +#[allow(deprecated)] impl ConfChangeSingle { #[inline] pub fn default_ref() -> &'static Self { @@ -715,6 +719,7 @@ impl ConfChangeSingle { self.node_id } } +#[allow(deprecated)] impl ConfChangeV2 { pub fn write_to_bytes( &self, diff --git a/scripts/ci.sh b/scripts/ci.sh new file mode 100755 index 0000000..2781776 --- /dev/null +++ b/scripts/ci.sh @@ -0,0 +1,42 @@ +# Copyright 2024 The Google raft-rs authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#!/usr/bin/env bash + +# Exit when any command fails +#set -e + +printf "\n// cargo fmt --all -- --check\n\n" +env cargo fmt --all -- --check + +printf "\n// cargo clippy --all --all-targets -- -D clippy::all && cargo clippy --no-default-features --features prost-codec --features std -- -D clippy::all\n\n" +env cargo clippy --all --all-targets -- -D clippy::all && cargo clippy --no-default-features --features prost-codec --features std -- -D clippy::all + +printf "\n// cargo build --no-default-features --features prost-codec --target x86_64-unknown-none\n\n" +env cargo build --no-default-features --features prost-codec --target x86_64-unknown-none + +printf "\n// cargo test --all --no-default-features --features=prost-codec --features=default-logger --no-fail-fast -- --nocapture\n\n" +env cargo test --all --no-default-features --features=prost-codec --features=default-logger --no-fail-fast -- --nocapture + +printf "\n// cargo test --all --no-fail-fast -- --nocapture\n\n" +env cargo test --all --no-fail-fast -- --nocapture + +printf "\n// cargo bench --all -- --test\n\n" +env cargo bench --all -- --test + +printf "\n// cargo test --tests --features failpoints --package harness -- --nocapture\n\n" +env cargo test --tests --features failpoints --package harness -- --nocapture + +printf "\n// cargo test --no-default-features --features prost-codec --features std -- --nocapture\n\n" +env cargo test --no-default-features --features prost-codec --features std -- --nocapture diff --git a/src/config.rs b/src/config.rs index e258ba3..53425fb 100644 --- a/src/config.rs +++ b/src/config.rs @@ -17,7 +17,7 @@ use alloc::borrow::ToOwned; use alloc::format; -pub use super::read_only::{ReadOnlyOption, ReadState}; +pub use super::read_only::ReadOnlyOption; use super::util::NO_LIMIT; use super::{ errors::{Error, Result}, diff --git a/src/lib.rs b/src/lib.rs index 8edc5a5..76604e3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -485,6 +485,7 @@ before taking old, removed peers offline. // We use `default` method a lot to be support prost and rust-protobuf at the // same time. And reassignment can be optimized by compiler. #![allow(clippy::field_reassign_with_default)] +#![allow(unused_imports)] #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(error_in_core))] diff --git a/src/quorum/majority.rs b/src/quorum/majority.rs index d4a2a27..c26f2cc 100644 --- a/src/quorum/majority.rs +++ b/src/quorum/majority.rs @@ -20,15 +20,13 @@ pub struct Configuration { impl core::fmt::Display for Configuration { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { - write!( - f, - "({})", - self.voters - .iter() - .map(|x| x.to_string()) - .collect::>() - .join(" ") - ) + let mut voters = self + .voters + .iter() + .map(|x| x.to_string()) + .collect::>(); + voters.sort(); + write!(f, "({})", voters.join(" ")) } } diff --git a/src/raft.rs b/src/raft.rs index 92e70f9..983d6d6 100644 --- a/src/raft.rs +++ b/src/raft.rs @@ -16,7 +16,6 @@ use alloc::vec::Vec; use core::cmp; -use core::convert::TryFrom; use core::ops::{Deref, DerefMut}; use rand::rngs::SmallRng; @@ -27,8 +26,8 @@ use crate::eraftpb::{ #[cfg(feature = "protobuf-codec")] use protobuf::Message as _; use raft_proto::ConfChangeI; -use rand::{self, Rng, SeedableRng}; -use slog::{self, Logger}; +use rand::{Rng, SeedableRng}; +use slog::Logger; #[cfg(feature = "failpoints")] use fail::fail_point; @@ -290,10 +289,6 @@ impl DerefMut for Raft { } } -trait AssertSend: Send {} - -impl AssertSend for Raft {} - fn new_message(to: u64, field_type: MessageType, from: Option) -> Message { let mut m = Message::default(); m.to = to; diff --git a/src/raft_log.rs b/src/raft_log.rs index 5a033f6..917bd56 100644 --- a/src/raft_log.rs +++ b/src/raft_log.rs @@ -668,6 +668,8 @@ impl RaftLog { #[cfg(test)] mod test { + #![allow(clippy::useless_vec)] + use alloc::vec; use crate::default_logger;