From e17bd832ce26534b42cf07f920f015ccef4a3676 Mon Sep 17 00:00:00 2001 From: bsbds <69835502+bsbds@users.noreply.github.com> Date: Mon, 5 Jun 2023 10:23:34 +0800 Subject: [PATCH] test: add tests for kv client in xline-client --- xline-client/Cargo.toml | 1 + xline-client/tests/kv.rs | 237 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 238 insertions(+) create mode 100644 xline-client/tests/kv.rs diff --git a/xline-client/Cargo.toml b/xline-client/Cargo.toml index 690e2805a..78c032ee5 100644 --- a/xline-client/Cargo.toml +++ b/xline-client/Cargo.toml @@ -28,4 +28,5 @@ pbkdf2 = { version = "0.11.0", features = ["std"] } http = "0.2.9" [dev-dependencies] +xline-test-utils = { path = "../xline-test-utils" } rand = "0.8.5" diff --git a/xline-client/tests/kv.rs b/xline-client/tests/kv.rs new file mode 100644 index 000000000..0e8363509 --- /dev/null +++ b/xline-client/tests/kv.rs @@ -0,0 +1,237 @@ +//! The following tests are originally from `etcd-client` +use xline_client::{ + clients::kv::{Compare, DeleteRangeRequest, PutRequest, RangeRequest, Txn, TxnOp}, + error::Result, + Client, ClientOptions, +}; +use xline_test_utils::Cluster; +use xlineapi::CompareResult; + +#[tokio::test] +async fn test_put() -> Result<()> { + let mut cluster = Cluster::new(3).await; + cluster.start().await; + let mut client = Client::connect(cluster.addrs().clone(), ClientOptions::default()) + .await? + .kv_client(); + let request = PutRequest::new("put", "123"); + client.put(request).await?; + + // overwrite with prev key + { + let request = PutRequest::new("put", "456").with_prev_kv(true); + let resp = client.put(request).await?; + let prev_kv = resp.prev_kv; + assert!(prev_kv.is_some()); + let prev_kv = prev_kv.unwrap(); + assert_eq!(prev_kv.key, b"put"); + assert_eq!(prev_kv.value, b"123"); + } + + // overwrite again with prev key + { + let request = PutRequest::new("put", "456").with_prev_kv(true); + let resp = client.put(request).await?; + let prev_kv = resp.prev_kv; + assert!(prev_kv.is_some()); + let prev_kv = prev_kv.unwrap(); + assert_eq!(prev_kv.key, b"put"); + assert_eq!(prev_kv.value, b"456"); + } + + Ok(()) +} + +#[tokio::test] +async fn test_get() -> Result<()> { + let mut cluster = Cluster::new(3).await; + cluster.start().await; + let mut client = Client::connect(cluster.addrs().clone(), ClientOptions::default()) + .await? + .kv_client(); + client.put(PutRequest::new("get10", "10")).await?; + client.put(PutRequest::new("get11", "11")).await?; + client.put(PutRequest::new("get20", "20")).await?; + client.put(PutRequest::new("get21", "21")).await?; + + // get key + { + let resp = client.range(RangeRequest::new("get11")).await?; + assert_eq!(resp.count, 1); + assert!(!resp.more); + assert_eq!(resp.kvs.len(), 1); + assert_eq!(resp.kvs[0].key, b"get11"); + assert_eq!(resp.kvs[0].value, b"11"); + } + + // get from key + { + let resp = client + .range(RangeRequest::new("get11").with_from_key().with_limit(2)) + .await?; + assert!(resp.more); + assert_eq!(resp.kvs.len(), 2); + assert_eq!(resp.kvs[0].key, b"get11"); + assert_eq!(resp.kvs[0].value, b"11"); + assert_eq!(resp.kvs[1].key, b"get20"); + assert_eq!(resp.kvs[1].value, b"20"); + } + + // get prefix keys + { + let resp = client + .range(RangeRequest::new("get1").with_prefix()) + .await?; + assert_eq!(resp.count, 2); + assert!(!resp.more); + assert_eq!(resp.kvs.len(), 2); + assert_eq!(resp.kvs[0].key, b"get10"); + assert_eq!(resp.kvs[0].value, b"10"); + assert_eq!(resp.kvs[1].key, b"get11"); + assert_eq!(resp.kvs[1].value, b"11"); + } + + Ok(()) +} + +#[tokio::test] +async fn test_delete() -> Result<()> { + let mut cluster = Cluster::new(3).await; + cluster.start().await; + let mut client = Client::connect(cluster.addrs().clone(), ClientOptions::default()) + .await? + .kv_client(); + client.put(PutRequest::new("del10", "10")).await?; + client.put(PutRequest::new("del11", "11")).await?; + client.put(PutRequest::new("del20", "20")).await?; + client.put(PutRequest::new("del21", "21")).await?; + client.put(PutRequest::new("del31", "31")).await?; + client.put(PutRequest::new("del32", "32")).await?; + + // delete key + { + let resp = client + .delete(DeleteRangeRequest::new("del11").with_prev_kv(true)) + .await?; + assert_eq!(resp.deleted, 1); + assert_eq!(&resp.prev_kvs[0].key, "del11".as_bytes()); + assert_eq!(&resp.prev_kvs[0].value, "11".as_bytes()); + let resp = client + .range(RangeRequest::new("del11").with_count_only(true)) + .await?; + assert_eq!(resp.count, 0); + } + + // delete a range of keys + { + let resp = client + .delete( + DeleteRangeRequest::new("del11") + .with_range_end("del22") + .with_prev_kv(true), + ) + .await?; + assert_eq!(resp.deleted, 2); + assert_eq!(&resp.prev_kvs[0].key, "del20".as_bytes()); + assert_eq!(&resp.prev_kvs[0].value, "20".as_bytes()); + assert_eq!(&resp.prev_kvs[1].key, "del21".as_bytes()); + assert_eq!(&resp.prev_kvs[1].value, "21".as_bytes()); + let resp = client + .range( + RangeRequest::new("del11") + .with_range_end("del22") + .with_count_only(true), + ) + .await?; + assert_eq!(resp.count, 0); + } + + // delete key with prefix + { + let resp = client + .delete( + DeleteRangeRequest::new("del3") + .with_prefix() + .with_prev_kv(true), + ) + .await?; + assert_eq!(resp.deleted, 2); + assert_eq!(&resp.prev_kvs[0].key, "del31".as_bytes()); + assert_eq!(&resp.prev_kvs[0].value, "31".as_bytes()); + assert_eq!(&resp.prev_kvs[1].key, "del32".as_bytes()); + assert_eq!(&resp.prev_kvs[1].value, "32".as_bytes()); + let resp = client + .range(RangeRequest::new("del32").with_count_only(true)) + .await?; + assert_eq!(resp.count, 0); + } + + Ok(()) +} + +#[tokio::test] +async fn test_txn() -> Result<()> { + let mut cluster = Cluster::new(3).await; + cluster.start().await; + let mut client = Client::connect(cluster.addrs().clone(), ClientOptions::default()) + .await? + .kv_client(); + + client.put(PutRequest::new("txn01", "01")).await?; + + // transaction 1 + { + let resp = client + .txn( + Txn::new() + .when(&[Compare::value("txn01", CompareResult::Equal, "01")][..]) + .and_then( + &[TxnOp::put( + PutRequest::new("txn01", "02").with_prev_kv(true), + )][..], + ) + .or_else(&[TxnOp::range(RangeRequest::new("txn01"))][..]), + ) + .await?; + + assert!(resp.succeeded); + let op_responses = resp.responses; + assert_eq!(op_responses.len(), 1); + + match op_responses[0].response.as_ref().unwrap() { + xlineapi::Response::ResponsePut(resp) => { + assert_eq!(resp.prev_kv.as_ref().unwrap().value, b"01") + } + _ => panic!("expect put response)"), + } + + let resp = client.range(RangeRequest::new("txn01")).await?; + assert_eq!(resp.kvs[0].key, b"txn01"); + assert_eq!(resp.kvs[0].value, b"02"); + } + + // transaction 2 + { + let resp = client + .txn( + Txn::new() + .when(&[Compare::value("txn01", CompareResult::Equal, "01")][..]) + .and_then(&[TxnOp::put(PutRequest::new("txn01", "02"))][..]) + .or_else(&[TxnOp::range(RangeRequest::new("txn01"))][..]), + ) + .await?; + + assert!(!resp.succeeded); + let op_responses = resp.responses; + assert_eq!(op_responses.len(), 1); + + match op_responses[0].response.as_ref().unwrap() { + xlineapi::Response::ResponseRange(resp) => { + assert_eq!(resp.kvs[0].value, b"02") + } + _ => panic!("expect range response)"), + } + } + + Ok(()) +}