From 75a5e060771ec9f63118d7b7e510246a6b79b5dc Mon Sep 17 00:00:00 2001 From: minhtrannhat Date: Sun, 21 Sep 2025 17:00:51 -0400 Subject: [PATCH] initial commit - Added basic structure so tests won't error --- .gitignore | 1 + .glimpse | 14 +++ Cargo.lock | 245 +++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 9 ++ src/bin/kvs.rs | 3 + src/lib.rs | 34 +++++++ tests/tests.rs | 155 +++++++++++++++++++++++++++++++ 7 files changed, 461 insertions(+) create mode 100644 .gitignore create mode 100644 .glimpse create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/bin/kvs.rs create mode 100644 src/lib.rs create mode 100644 tests/tests.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/.glimpse b/.glimpse new file mode 100644 index 0000000..092fa5a --- /dev/null +++ b/.glimpse @@ -0,0 +1,14 @@ +exclude = [ + "**/.git/**", + "**/.svn/**", + "**/.hg/**", + "**/target/**", + "**/node_modules/**", + "**/dist/**", + "**/build/**", +] +max_size = 10485760 +max_depth = 20 +output = "both" +hidden = false +no_ignore = false diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..8466c01 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,245 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstyle" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" + +[[package]] +name = "assert_cmd" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bd389a4b2970a01282ee455294913c0a43724daedcd1a24c3eb0ec1c1320b66" +dependencies = [ + "anstyle", + "bstr", + "doc-comment", + "libc", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bstr" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "float-cmp" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8" +dependencies = [ + "num-traits", +] + +[[package]] +name = "kvs" +version = "0.1.0" +dependencies = [ + "assert_cmd", + "predicates", +] + +[[package]] +name = "libc" +version = "0.2.175" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "predicates" +version = "3.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" +dependencies = [ + "anstyle", + "difflib", + "float-cmp", + "normalize-line-endings", + "predicates-core", + "regex", +] + +[[package]] +name = "predicates-core" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa" + +[[package]] +name = "predicates-tree" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c" +dependencies = [ + "predicates-core", + "termtree", +] + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" + +[[package]] +name = "serde" +version = "1.0.226" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b51295fd" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.226" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba2ba63999edb9dac981fb34b3e5c0d111a69b0924e253ed29d83f7c99e966a4" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.226" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699cdb33" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termtree" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" + +[[package]] +name = "unicode-ident" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" + +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..8bb73dd --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "kvs" +version = "0.1.0" +authors = ["Minh Tran "] +edition = "2024" + +[dependencies] +assert_cmd = "2.0.17" +predicates = "3.1.3" diff --git a/src/bin/kvs.rs b/src/bin/kvs.rs new file mode 100644 index 0000000..7b70802 --- /dev/null +++ b/src/bin/kvs.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, wolrld"); +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..b991162 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,34 @@ +pub struct KvStore {} + +impl KvStore { + pub fn new() -> Self { + unimplemented!() + } + + pub fn set(&mut self, key: String, value: String) { + unimplemented!() + } + + pub fn get(&mut self, key: String) -> Option { + unimplemented!() + } + + pub fn remove(&mut self, key: String) { + unimplemented!() + } +} + +pub fn add(left: u64, right: u64) -> u64 { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} diff --git a/tests/tests.rs b/tests/tests.rs new file mode 100644 index 0000000..16ee0c9 --- /dev/null +++ b/tests/tests.rs @@ -0,0 +1,155 @@ +use assert_cmd::prelude::*; +use kvs::KvStore; +use predicates::str::contains; +use std::process::Command; + +// `kvs` with no args should exit with a non-zero code. +#[test] +fn cli_no_args() { + Command::cargo_bin("kvs").unwrap().assert().failure(); +} + +// `kvs -V` should print the version +#[test] +fn cli_version() { + Command::cargo_bin("kvs") + .unwrap() + .args(&["-V"]) + .assert() + .stdout(contains(env!("CARGO_PKG_VERSION"))); +} + +// `kvs get ` should print "unimplemented" to stderr and exit with non-zero code +#[test] +fn cli_get() { + Command::cargo_bin("kvs") + .unwrap() + .args(&["get", "key1"]) + .assert() + .failure() + .stderr(contains("unimplemented")); +} + +// `kvs set ` should print "unimplemented" to stderr and exit with non-zero code +#[test] +fn cli_set() { + Command::cargo_bin("kvs") + .unwrap() + .args(&["set", "key1", "value1"]) + .assert() + .failure() + .stderr(contains("unimplemented")); +} + +// `kvs rm ` should print "unimplemented" to stderr and exit with non-zero code +#[test] +fn cli_rm() { + Command::cargo_bin("kvs") + .unwrap() + .args(&["rm", "key1"]) + .assert() + .failure() + .stderr(contains("unimplemented")); +} + +#[test] +fn cli_invalid_get() { + Command::cargo_bin("kvs") + .unwrap() + .args(&["get"]) + .assert() + .failure(); + + Command::cargo_bin("kvs") + .unwrap() + .args(&["get", "extra", "field"]) + .assert() + .failure(); +} + +#[test] +fn cli_invalid_set() { + Command::cargo_bin("kvs") + .unwrap() + .args(&["set"]) + .assert() + .failure(); + + Command::cargo_bin("kvs") + .unwrap() + .args(&["set", "missing_field"]) + .assert() + .failure(); + + Command::cargo_bin("kvs") + .unwrap() + .args(&["set", "extra", "extra", "field"]) + .assert() + .failure(); +} + +#[test] +fn cli_invalid_rm() { + Command::cargo_bin("kvs") + .unwrap() + .args(&["rm"]) + .assert() + .failure(); + + Command::cargo_bin("kvs") + .unwrap() + .args(&["rm", "extra", "field"]) + .assert() + .failure(); +} + +#[test] +fn cli_invalid_subcommand() { + Command::cargo_bin("kvs") + .unwrap() + .args(&["unknown", "subcommand"]) + .assert() + .failure(); +} + +// Should get previously stored value +#[test] +fn get_stored_value() { + let mut store = KvStore::new(); + + store.set("key1".to_owned(), "value1".to_owned()); + store.set("key2".to_owned(), "value2".to_owned()); + + assert_eq!(store.get("key1".to_owned()), Some("value1".to_owned())); + assert_eq!(store.get("key2".to_owned()), Some("value2".to_owned())); +} + +// Should overwrite existent value +#[test] +fn overwrite_value() { + let mut store = KvStore::new(); + + store.set("key1".to_owned(), "value1".to_owned()); + assert_eq!(store.get("key1".to_owned()), Some("value1".to_owned())); + + store.set("key1".to_owned(), "value2".to_owned()); + assert_eq!(store.get("key1".to_owned()), Some("value2".to_owned())); +} + +// Should get `None` when getting a non-existent key +#[test] +fn get_non_existent_value() { + let mut store = KvStore::new(); + + store.set("key1".to_owned(), "value1".to_owned()); + assert_eq!(store.get("key2".to_owned()), None); +} + +#[test] +fn remove_key() { + let mut store = KvStore::new(); + + store.set("key1".to_owned(), "value1".to_owned()); + store.remove("key1".to_owned()); + assert_eq!(store.get("key1".to_owned()), None); +}