Skip to content

Commit e1ae1cf

Browse files
committed
Add talent-plant TP-201
1 parent 9551eac commit e1ae1cf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+11305
-0
lines changed

README.org

+10
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,13 @@ Based on examples from [[https://book.douban.com/subject/30312231/][《深入浅
4141
| 13.2.1 | [[file:mastering-rust/ch13_web/hyperurl/src/main.rs][hyperurl]] |
4242
| 13.2.2 | [[file:mastering-rust/ch13_web/shorten/src/main.rs][shorten]] |
4343
| 13.4 | [[file:mastering-rust/ch13_web/linksnap/src/main.rs][linksnap]] |
44+
45+
* talent-plan
46+
Rust and distributed systems training courses from [[https://github.com/pingcap/talent-plan][PingCAP talent-plan]].
47+
** Series 2: Rust Programming
48+
*** TP 201: Practical Networked Applications in Rust
49+
- [[file:talent-plan/rust/project-1/src/kv.rs][project-1]]
50+
- [[file:talent-plan/rust/project-2/src/kv.rs][project-2]]
51+
- [[file:talent-plan/rust/project-3/src/lib.rs][project-3]]
52+
- [[file:talent-plan/rust/project-4/src/lib.rs][project-4]]
53+
- [[file:talent-plan/rust/project-5/src/lib.rs][project-5]]

talent-plan/rust/project-1/Cargo.lock

+353
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

talent-plan/rust/project-1/Cargo.toml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "kvs"
3+
version = "0.1.0"
4+
authors = ["ShuLiang <[email protected]>"]
5+
description = "A key-value store"
6+
edition = "2018"
7+
8+
[dependencies]
9+
assert_cmd = "0.11.0"
10+
predicates = "1.0.0"
11+
clap = "2.33.0"
+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#[macro_use]
2+
extern crate clap;
3+
4+
use std::process::exit;
5+
6+
fn main() {
7+
let matches = clap_app!(
8+
kvs =>
9+
(@setting DisableHelpSubcommand)
10+
(@setting SubcommandRequiredElseHelp)
11+
(@setting VersionlessSubcommands)
12+
(version: env!("CARGO_PKG_VERSION"))
13+
(author: env!("CARGO_PKG_AUTHORS"))
14+
(about: env!("CARGO_PKG_DESCRIPTION"))
15+
(@subcommand set =>
16+
(about: "Set the value of a string key to a string")
17+
(@arg KEY: +required "A string key")
18+
(@arg VALUE: +required "The string value of the key")
19+
)
20+
(@subcommand get =>
21+
(about: "Get the string value of a given string key")
22+
(@arg KEY: +required "A string key")
23+
)
24+
(@subcommand rm =>
25+
(about: "Remove a given key")
26+
(@arg KEY: +required "A string key")
27+
)
28+
)
29+
.get_matches();
30+
31+
match matches.subcommand() {
32+
("set", Some(_matches)) => {
33+
eprintln!("unimplemented");
34+
exit(1);
35+
}
36+
("get", Some(_matches)) => {
37+
eprintln!("unimplemented");
38+
exit(1);
39+
}
40+
("rm", Some(_matches)) => {
41+
eprintln!("unimplemented");
42+
exit(1);
43+
}
44+
_ => unreachable!(),
45+
}
46+
}

talent-plan/rust/project-1/src/kv.rs

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
use std::collections::HashMap;
2+
3+
/// The `KvStore` stores string key-value pairs.
4+
///
5+
/// Key-value paris are stored in a `HashMap` in memory and not persisited to disk.
6+
///
7+
/// Example:
8+
///
9+
/// ```rust
10+
/// # use kvs::KvStore;
11+
/// let mut store = KvStore::new();
12+
/// store.set("key".to_owned(), "value".to_owned());
13+
/// let val = store.get("key".to_owned());
14+
/// assert_eq!(val, Some("value".to_owned()));
15+
/// ```
16+
#[derive(Default)]
17+
pub struct KvStore {
18+
store: HashMap<String, String>,
19+
}
20+
21+
impl KvStore {
22+
/// Create a `KvStore`.
23+
pub fn new() -> Self {
24+
KvStore {
25+
store: HashMap::new(),
26+
}
27+
}
28+
29+
/// Sets the value of a string key to a string.
30+
///
31+
/// Overwrites previous value if the key already exists.
32+
pub fn set(&mut self, key: String, value: String) {
33+
self.store.insert(key, value);
34+
}
35+
36+
/// Gets the string value of a given string key.
37+
///
38+
/// Returns `None` if the given key does not exist.
39+
pub fn get(&mut self, key: String) -> Option<String> {
40+
self.store.get(&key).cloned()
41+
}
42+
43+
/// Remove a given key
44+
pub fn remove(&mut self, key: String) {
45+
self.store.remove(&key);
46+
}
47+
}

talent-plan/rust/project-1/src/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#![deny(missing_docs)]
2+
//! A simple key/value store.
3+
4+
pub use kv::KvStore;
5+
6+
mod kv;
+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
use assert_cmd::prelude::*;
2+
use kvs::KvStore;
3+
use predicates::str::contains;
4+
use std::process::Command;
5+
6+
// `kvs` with no args should exit with a non-zero code.
7+
#[test]
8+
fn cli_no_args() {
9+
Command::cargo_bin("kvs").unwrap().assert().failure();
10+
}
11+
12+
// `kvs -V` should print the version
13+
#[test]
14+
fn cli_version() {
15+
Command::cargo_bin("kvs")
16+
.unwrap()
17+
.args(&["-V"])
18+
.assert()
19+
.stdout(contains(env!("CARGO_PKG_VERSION")));
20+
}
21+
22+
// `kvs get <KEY>` should print "unimplemented" to stderr and exit with non-zero code
23+
#[test]
24+
fn cli_get() {
25+
Command::cargo_bin("kvs")
26+
.unwrap()
27+
.args(&["get", "key1"])
28+
.assert()
29+
.failure()
30+
.stderr(contains("unimplemented"));
31+
}
32+
33+
// `kvs set <KEY> <VALUE>` should print "unimplemented" to stderr and exit with non-zero code
34+
#[test]
35+
fn cli_set() {
36+
Command::cargo_bin("kvs")
37+
.unwrap()
38+
.args(&["set", "key1", "value1"])
39+
.assert()
40+
.failure()
41+
.stderr(contains("unimplemented"));
42+
}
43+
44+
// `kvs rm <KEY>` should print "unimplemented" to stderr and exit with non-zero code
45+
#[test]
46+
fn cli_rm() {
47+
Command::cargo_bin("kvs")
48+
.unwrap()
49+
.args(&["rm", "key1"])
50+
.assert()
51+
.failure()
52+
.stderr(contains("unimplemented"));
53+
}
54+
55+
#[test]
56+
fn cli_invalid_get() {
57+
Command::cargo_bin("kvs")
58+
.unwrap()
59+
.args(&["get"])
60+
.assert()
61+
.failure();
62+
63+
Command::cargo_bin("kvs")
64+
.unwrap()
65+
.args(&["get", "extra", "field"])
66+
.assert()
67+
.failure();
68+
}
69+
70+
#[test]
71+
fn cli_invalid_set() {
72+
Command::cargo_bin("kvs")
73+
.unwrap()
74+
.args(&["set"])
75+
.assert()
76+
.failure();
77+
78+
Command::cargo_bin("kvs")
79+
.unwrap()
80+
.args(&["set", "missing_field"])
81+
.assert()
82+
.failure();
83+
84+
Command::cargo_bin("kvs")
85+
.unwrap()
86+
.args(&["set", "extra", "extra", "field"])
87+
.assert()
88+
.failure();
89+
}
90+
91+
#[test]
92+
fn cli_invalid_rm() {
93+
Command::cargo_bin("kvs")
94+
.unwrap()
95+
.args(&["rm"])
96+
.assert()
97+
.failure();
98+
99+
Command::cargo_bin("kvs")
100+
.unwrap()
101+
.args(&["rm", "extra", "field"])
102+
.assert()
103+
.failure();
104+
}
105+
106+
#[test]
107+
fn cli_invalid_subcommand() {
108+
Command::cargo_bin("kvs")
109+
.unwrap()
110+
.args(&["unknown", "subcommand"])
111+
.assert()
112+
.failure();
113+
}
114+
115+
// Should get previously stored value
116+
#[test]
117+
fn get_stored_value() {
118+
let mut store = KvStore::new();
119+
120+
store.set("key1".to_owned(), "value1".to_owned());
121+
store.set("key2".to_owned(), "value2".to_owned());
122+
123+
assert_eq!(store.get("key1".to_owned()), Some("value1".to_owned()));
124+
assert_eq!(store.get("key2".to_owned()), Some("value2".to_owned()));
125+
}
126+
127+
// Should overwrite existent value
128+
#[test]
129+
fn overwrite_value() {
130+
let mut store = KvStore::new();
131+
132+
store.set("key1".to_owned(), "value1".to_owned());
133+
assert_eq!(store.get("key1".to_owned()), Some("value1".to_owned()));
134+
135+
store.set("key1".to_owned(), "value2".to_owned());
136+
assert_eq!(store.get("key1".to_owned()), Some("value2".to_owned()));
137+
}
138+
139+
// Should get `None` when getting a non-existent key
140+
#[test]
141+
fn get_non_existent_value() {
142+
let mut store = KvStore::new();
143+
144+
store.set("key1".to_owned(), "value1".to_owned());
145+
assert_eq!(store.get("key2".to_owned()), None);
146+
}
147+
148+
#[test]
149+
fn remove_key() {
150+
let mut store = KvStore::new();
151+
152+
store.set("key1".to_owned(), "value1".to_owned());
153+
store.remove("key1".to_owned());
154+
assert_eq!(store.get("key1".to_owned()), None);
155+
}

0 commit comments

Comments
 (0)