Browse Source

quest 08: tests and subject

content-update
lee 3 years ago
parent
commit
6bd54ffb5c
  1. 12
      rust/tests/borrow_box_test/Cargo.lock
  2. 10
      rust/tests/borrow_box_test/Cargo.toml
  3. 91
      rust/tests/borrow_box_test/src/main.rs
  4. 12
      rust/tests/box_it_test/Cargo.lock
  5. 10
      rust/tests/box_it_test/Cargo.toml
  6. 56
      rust/tests/box_it_test/src/main.rs
  7. 12
      rust/tests/box_recursion_test/Cargo.lock
  8. 10
      rust/tests/box_recursion_test/Cargo.toml
  9. 98
      rust/tests/box_recursion_test/src/main.rs
  10. 12
      rust/tests/drop_the_thread_test/Cargo.lock
  11. 10
      rust/tests/drop_the_thread_test/Cargo.toml
  12. 87
      rust/tests/drop_the_thread_test/src/main.rs
  13. 12
      rust/tests/how_many_references_test/Cargo.lock
  14. 10
      rust/tests/how_many_references_test/Cargo.toml
  15. 103
      rust/tests/how_many_references_test/src/main.rs
  16. 12
      rust/tests/ref_cell_test/Cargo.lock
  17. 10
      rust/tests/ref_cell_test/Cargo.toml
  18. 158
      rust/tests/ref_cell_test/src/main.rs
  19. 83
      subjects/borrow_box/README.md
  20. 53
      subjects/box_it/README.md
  21. 79
      subjects/box_recursion/README.md
  22. 109
      subjects/drop_the_thread/README.md
  23. 78
      subjects/how_many_references/README.md
  24. 112
      subjects/ref_cell/README.md

12
rust/tests/borrow_box_test/Cargo.lock diff.generated

@ -0,0 +1,12 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "borrow_box"
version = "0.1.0"
[[package]]
name = "borrow_box_test"
version = "0.1.0"
dependencies = [
"borrow_box",
]

10
rust/tests/borrow_box_test/Cargo.toml

@ -0,0 +1,10 @@
[package]
name = "borrow_box_test"
version = "0.1.0"
authors = ["lee <lee-dasilva@hotmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
borrow_box = { path = "../../../../rust-piscine-solutions/borrow_box"}

91
rust/tests/borrow_box_test/src/main.rs

@ -0,0 +1,91 @@
use borrow_box::*;
fn main() {
let mut game = Game::new(0, String::from("Joao"), String::from("Susana"), 5);
println!("{:?}", game.read_winner());
// output : ("Same score! tied", 0)
game.update_score(String::from("Joao"));
game.update_score(String::from("Joao"));
game.update_score(String::from("Susana"));
game.update_score(String::from("Susana"));
println!("{:?}", game.read_winner());
// output : ("Same score! tied", 2)
game.update_score(String::from("Joao"));
// this one will not count because it already 5 games played, the nbr_of_games
game.update_score(String::from("Susana"));
println!("{:?}", game.read_winner());
// output : ("Joao", 3)
println!("{:?}", game.delete());
// output : "game deleted: id -> 0"
// game.read_winner();
// this will give error
// because the game was dropped, no longer exists on the heap
}
#[cfg(test)]
mod tests {
use super::*;
fn create_games() -> Vec<Box<Game>> {
vec![
Game::new(0, String::from("player1"), String::from("player2"), 1),
Game::new(1, String::from("Alice"), String::from("Mark"), 3),
Game::new(2, String::from("Jack"), String::from("Miller"), 5)
]
}
#[test]
fn test_create() {
let games = create_games();
assert_eq!(*games[0], Game {id: 0, p1: (String::from("player1"), 0), p2: (String::from("player2"), 0), nbr_of_games: 1});
assert_eq!(*games[1], Game {id: 1, p1: (String::from("Alice"), 0), p2: (String::from("Mark"), 0), nbr_of_games: 3});
assert_eq!(*games[2], Game {id: 2, p1: (String::from("Jack"), 0), p2: (String::from("Miller"), 0), nbr_of_games: 5});
}
#[test]
fn test_update_and_read() {
let mut games = create_games();
games[0].update_score(String::from("player1"));
assert_eq!(games[0].read_winner(), (String::from("player1"), 1));
games[0].update_score(String::from("player2"));
// this will stay the same because the nbr_of_games is 1 so if one
// of the players wins just once it will no longer increment the score
assert_eq!(games[0].read_winner(), (String::from("player1"), 1));
games[2].update_score(String::from("Jack"));
games[2].update_score(String::from("Jack"));
games[2].update_score(String::from("Miller"));
games[2].update_score(String::from("Miller"));
// tie between players
assert_eq!(games[2].read_winner(), (String::from("Same score! tied"), 2));
games[2].update_score(String::from("Jack"));
assert_eq!(games[2].read_winner(), (String::from("Jack"), 3));
}
#[test]
fn test_delete() {
let game = Game::new(0, String::from("Alice"), String::from("Mark"), 3);
let game1 = Game::new(23, String::from("Jack"), String::from("Miller"), 1);
assert_eq!(game.delete(), String::from("game deleted: id -> 0"));
assert_eq!(game1.delete(), String::from("game deleted: id -> 23"));
}
// #[test]
// #[should_panic]
// fn test_delete_ownership() {
// let game = new(0, String::from("Alice"), String::from("Mark"), 3);
// {
// let a = &game;
// // error! cant destroy boxed while the inner value is borrowed later in scope
// delete(game);
// read_winner(&a);
// }
// }
}

12
rust/tests/box_it_test/Cargo.lock diff.generated

@ -0,0 +1,12 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "box_it"
version = "0.1.0"
[[package]]
name = "box_it_test"
version = "0.1.0"
dependencies = [
"box_it",
]

10
rust/tests/box_it_test/Cargo.toml

@ -0,0 +1,10 @@
[package]
name = "box_it_test"
version = "0.1.0"
authors = ["lee <lee-dasilva@hotmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
box_it = { path = "../../../../rust-piscine-solutions/box_it"}

56
rust/tests/box_it_test/src/main.rs

@ -0,0 +1,56 @@
use box_it::*;
fn main() {
let new_str = String::from("5.5k 8.9k 32");
// creating a variable and we save it in the Heap
let a_h = transform_and_save_on_heap(new_str);
println!("Box value : {:?}", &a_h);
println!("size occupied in the stack : {:?} bytes", (std::mem::size_of_val(&a_h)));
let a_b_v = take_value_ownership(a_h);
println!("value : {:?}", &a_b_v);
println!("size occupied in the stack : {:?} bytes", (std::mem::size_of_val(&a_b_v)));
// whenever the box, in this case "a_h", goes out of scope it will be deallocated, freed
}
#[cfg(test)]
mod tests {
use super::*;
use std::mem;
#[test]
fn test_transform() {
let new_str = String::from("5.5k 8.9k 32");
let new_str_1 = String::from("6.8k 13.5k");
let new_str_2 = String::from("20.3k 3.8k 7.7k 992");
let a = transform_and_save_on_heap(new_str);
let b = transform_and_save_on_heap(new_str_1);
let c = transform_and_save_on_heap(new_str_2);
assert_eq!(a, Box::new(vec![5500, 8900, 32]));
assert_eq!(b, Box::new(vec![6800, 13500]));
assert_eq!(c, Box::new(vec![20300, 3800, 7700, 992]));
assert_eq!(mem::size_of_val(&a), 8);
assert_eq!(mem::size_of_val(&b), 8);
assert_eq!(mem::size_of_val(&c), 8);
}
#[test]
fn test_take_value_from_box() {
let new_str = String::from("5.5k 8.9k 32");
let new_str_1 = String::from("6.8k 13.5k");
let new_str_2 = String::from("20.3k 3.8k 7.7k 992");
let a = take_value_ownership(transform_and_save_on_heap(new_str));
let b = take_value_ownership(transform_and_save_on_heap(new_str_1));
let c = take_value_ownership(transform_and_save_on_heap(new_str_2));
assert_eq!(a, vec![5500, 8900, 32]);
assert_eq!(b, vec![6800, 13500]);
assert_eq!(c, vec![20300, 3800, 7700, 992]);
assert_eq!(mem::size_of_val(&a), 24);
assert_eq!(mem::size_of_val(&b), 24);
assert_eq!(mem::size_of_val(&c), 24);
}
}

12
rust/tests/box_recursion_test/Cargo.lock diff.generated

@ -0,0 +1,12 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "box_recursion"
version = "0.1.0"
[[package]]
name = "box_recursion_test"
version = "0.1.0"
dependencies = [
"box_recursion",
]

10
rust/tests/box_recursion_test/Cargo.toml

@ -0,0 +1,10 @@
[package]
name = "box_recursion_test"
version = "0.1.0"
authors = ["lee <lee-dasilva@hotmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
box_recursion = { path = "../../../../rust-piscine-solutions/box_recursion"}

98
rust/tests/box_recursion_test/src/main.rs

@ -0,0 +1,98 @@
use box_recursion::*;
fn main() {
let mut list = WorkEnvironment::new();
list.add_worker(String::from("CEO"), String::from("Marie"));
list.add_worker(String::from("Manager"), String::from("Monica"));
list.add_worker(String::from("Normal Worker"), String::from("Ana"));
list.add_worker(String::from("Normal Worker"), String::from("Alice"));
println!("{:?}", list);
println!("{:?}", list.search_worker());
list.remove_worker();
list.remove_worker();
list.remove_worker();
list.remove_worker();
println!("{:?}", list);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new() {
let list = WorkEnvironment::new();
assert!(list.grade.is_none());
}
#[test]
fn test_one_worker() {
let mut list = WorkEnvironment::new();
list.add_worker(String::from("CEO"), String::from("Marie"));
list.remove_worker();
assert!(list.grade.is_none());
}
#[test]
fn test_two_workers() {
let mut list = WorkEnvironment::new();
list.add_worker(String::from("CEO"), String::from("Marie"));
list.add_worker(String::from("Manager"), String::from("Monica"));
list.remove_worker();
assert_eq!(list.grade.as_ref().unwrap().worker_type, "CEO");
assert_eq!(list.grade.as_ref().unwrap().worker_name, "Marie");
}
#[test]
fn test_more_workers() {
let mut list = WorkEnvironment::new();
list.add_worker(String::from("CEO"), String::from("Marie"));
list.add_worker(String::from("Manager"), String::from("Monica"));
list.add_worker(String::from("Normal Worker"), String::from("Ana"));
list.add_worker(String::from("Normal Worker"), String::from("Alice"));
list.remove_worker();
assert_eq!(list.grade.as_ref().unwrap().worker_type, "Normal Worker");
assert_eq!(list.grade.as_ref().unwrap().worker_name, "Ana");
list.remove_worker();
list.remove_worker();
assert_eq!(list.grade.as_ref().unwrap().worker_type, "CEO");
assert_eq!(list.grade.as_ref().unwrap().worker_name, "Marie");
}
#[test]
fn test_search() {
let mut list = WorkEnvironment::new();
list.add_worker(String::from("CEO"), String::from("Marie"));
list.add_worker(String::from("Manager"), String::from("Monica"));
list.add_worker(String::from("Normal Worker"), String::from("Ana"));
list.add_worker(String::from("Normal Worker"), String::from("Alice"));
assert_eq!(
list.search_worker().unwrap(),
(String::from("Alice"), String::from("Normal Worker"))
);
list.remove_worker();
assert_eq!(
list.search_worker().unwrap(),
(String::from("Ana"), String::from("Normal Worker"))
);
list.remove_worker();
assert_eq!(
list.search_worker().unwrap(),
(String::from("Monica"), String::from("Manager"))
);
list.remove_worker();
assert_eq!(
list.search_worker().unwrap(),
(String::from("Marie"), String::from("CEO"))
);
}
}

12
rust/tests/drop_the_thread_test/Cargo.lock diff.generated

@ -0,0 +1,12 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "drop_the_thread"
version = "0.1.0"
[[package]]
name = "drop_the_thread_test"
version = "0.1.0"
dependencies = [
"drop_the_thread",
]

10
rust/tests/drop_the_thread_test/Cargo.toml

@ -0,0 +1,10 @@
[package]
name = "drop_the_thread_test"
version = "0.1.0"
authors = ["lee <lee-dasilva@hotmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
drop_the_thread = { path = "../../../../rust-piscine-solutions/drop_the_thread"}

87
rust/tests/drop_the_thread_test/src/main.rs

@ -0,0 +1,87 @@
use drop_the_thread::*;
use std::rc::Rc;
fn main() {
let worker = Workers::new();
let (id, thread) = worker.new_worker(String::from("command"));
let (id1, thread1) = worker.new_worker(String::from("command1"));
thread.skill();
println!("{:?}", (worker.is_dropped(id), id, &worker.drops));
// output: (true, 0, Cell { value: 1 })
thread1.skill();
println!("{:?}", (worker.is_dropped(id1), id1, &worker.drops));
// output: (true, 1, Cell { value: 2 })
let (id2, thread2) = worker.new_worker(String::from("command2"));
let thread2 = Rc::new(thread2);
let thread2_clone = thread2.clone();
// thread2_clone.skill();
drop(thread2_clone);
println!("{:?}", (worker.is_dropped(id2), id2, &worker.drops, Rc::strong_count(&thread2)));
// (false, 2, Cell { value: 2 }, 1)
}
#[cfg(test)]
mod tests {
use super::*;
use std::rc::Rc;
#[test]
fn test_is_dropped_and_drops() {
let worker = Workers::new();
let (pid, thread) = worker.new_worker(String::from("gnome-shell"));
let (pid0, thread0) = worker.new_worker(String::from("i3"));
let (pid1, thread1) = worker.new_worker(String::from("shell"));
let (pid2, thread2) = worker.new_worker(String::from("spotify"));
thread.skill();
assert_eq!(worker.drops.get(), 1_usize);
thread0.skill();
assert!(worker.is_dropped(pid), "{} should have been dropped", pid);
assert!(worker.is_dropped(pid0), "{} should have been dropped", pid0);
assert!(!worker.is_dropped(pid1), "{} should not have been dropped", pid1);
assert!(!worker.is_dropped(pid2), "{} should not have been dropped", pid2);
assert_eq!(worker.drops.get(), 2_usize);
thread1.skill();
thread2.skill();
assert_eq!(worker.drops.get(), 4_usize);
}
#[test]
fn test_using_rc() {
// will create a new reference to the thread
// this will test the following
// if we drop the cloned value the RC will decrease
// but the thread will not be dropped!
let worker = Workers::new();
let (_, thread) = worker.new_worker(String::from("Xorg"));
let thread = Rc::new(thread);
let thread_clone = thread.clone();
assert_eq!(Rc::strong_count(&thread), 2);
drop(thread_clone);
assert_eq!(Rc::strong_count(&thread), 1);
}
#[test]
#[should_panic(expected = "0 is already dropped")]
fn test_drop_same_thread() {
// test if we drop the same thread after it was already been dropped
let worker = Workers::new();
let (pid, thread) = worker.new_worker(String::from("gsd-rfkill"));
let thread_clone = thread.clone();
thread.skill();
thread_clone.skill();
}
}

12
rust/tests/how_many_references_test/Cargo.lock diff.generated

@ -0,0 +1,12 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "how_many_references"
version = "0.1.0"
[[package]]
name = "how_many_references_test"
version = "0.1.0"
dependencies = [
"how_many_references",
]

10
rust/tests/how_many_references_test/Cargo.toml

@ -0,0 +1,10 @@
[package]
name = "how_many_references_test"
version = "0.1.0"
authors = ["lee <lee-dasilva@hotmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
how_many_references = { path = "../../../../rust-piscine-solutions/how_many_references"}

103
rust/tests/how_many_references_test/src/main.rs

@ -0,0 +1,103 @@
use how_many_references::*;
fn main() {
let a = Rc::new(String::from("a"));
let b = Rc::new(String::from("b"));
let c = Rc::new(String::from("c"));
let a1 = Rc::new(String::from("a"));
let mut new_node = Node::new(vec![a.clone()]);
new_node.add_ele(b.clone());
new_node.add_ele(a.clone());
new_node.add_ele(c.clone());
new_node.add_ele(a.clone());
println!("a: {:?}", how_many_references(&a));
println!("b: {:?}", how_many_references(&b));
println!("c: {:?}", how_many_references(&c));
new_node.rm_all_ref(a1.clone());
new_node.rm_all_ref(a.clone());
println!("a: {:?}", how_many_references(&a));
println!("b: {:?}", how_many_references(&b));
println!("c: {:?}", how_many_references(&c));
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add_ele() {
let a = Rc::new(String::from("a"));
let b = Rc::new(String::from("b"));
let c = Rc::new(String::from("c"));
let mut new_node = Node::new(vec![a.clone()]);
new_node.add_ele(a.clone());
new_node.add_ele(b.clone());
new_node.add_ele(c.clone());
assert_eq!(new_node.value, vec![a.clone(), a, b, c]);
}
#[test]
fn test_how_many_references() {
let a = Rc::new(String::from("a"));
let b = Rc::new(String::from("b"));
let c = Rc::new(String::from("c"));
let d = Rc::new(String::from("d"));
let mut new_node = Node::new(vec![]);
new_node.add_ele(b.clone());
new_node.add_ele(a.clone());
new_node.add_ele(c.clone());
new_node.add_ele(a.clone());
assert_eq!(how_many_references(&d), 1);
assert_eq!(how_many_references(&a), 3);
assert_eq!(how_many_references(&b), 2);
assert_eq!(how_many_references(&c), 2);
}
#[test]
fn test_rm_all_ref() {
let a = Rc::new(String::from("a"));
let b = Rc::new(String::from("b"));
let c = Rc::new(String::from("c"));
let d = Rc::new(String::from("d"));
let a1 = Rc::new(String::from("a"));
let b1 = Rc::new(String::from("b"));
let c1 = Rc::new(String::from("c"));
let d1 = Rc::new(String::from("d"));
let mut new_node = Node::new(vec![
d.clone(),
d.clone(),
b.clone(),
a.clone(),
c.clone(),
a.clone(),
d.clone(),
]);
new_node.rm_all_ref(a1.clone());
assert_eq!(how_many_references(&a), 3);
new_node.rm_all_ref(a.clone());
assert_eq!(how_many_references(&a), 1);
new_node.rm_all_ref(b1.clone());
assert_eq!(how_many_references(&b), 2);
new_node.rm_all_ref(b.clone());
assert_eq!(how_many_references(&b), 1);
new_node.rm_all_ref(c1.clone());
assert_eq!(how_many_references(&c), 2);
new_node.rm_all_ref(c.clone());
assert_eq!(how_many_references(&c), 1);
new_node.rm_all_ref(d1.clone());
assert_eq!(how_many_references(&d), 4);
new_node.rm_all_ref(d.clone());
assert_eq!(how_many_references(&d), 1);
}
}

12
rust/tests/ref_cell_test/Cargo.lock diff.generated

@ -0,0 +1,12 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "ref_cell"
version = "0.1.0"
[[package]]
name = "ref_cell_test"
version = "0.1.0"
dependencies = [
"ref_cell",
]

10
rust/tests/ref_cell_test/Cargo.toml

@ -0,0 +1,10 @@
[package]
name = "ref_cell_test"
version = "0.1.0"
authors = ["lee <lee-dasilva@hotmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
ref_cell = { path = "../../../../rust-piscine-solutions/ref_cell"}

158
rust/tests/ref_cell_test/src/main.rs

@ -0,0 +1,158 @@
use ref_cell::*;
fn main() {
// initialize the worker
let Logger = Worker::new(1);
// initialize the tracker, with the max number of
// called references as 10
let track = Tracker::new(&Logger, 10);
let _a = Logger.track_value.clone(); // |\
let _a1 = Logger.track_value.clone(); // | -> increase the Rc to 4 references
let _a2 = Logger.track_value.clone(); // |/
// take a peek of how much we already used from our quota
track.peek(&Logger.track_value);
let _b = Logger.track_value.clone(); // |\
let _b1 = Logger.track_value.clone(); // | -> increase the Rc to 8 references
let _b2 = Logger.track_value.clone(); // | /
let _b3 = Logger.track_value.clone(); // |/
// this will set the value and making a verification of
// how much we already used of our quota
track.set_value(&Logger.track_value);
let _c = Logger.track_value.clone(); // | -> increase the Rc to 9 references
// this will set the value and making a verification of
// how much we already used of our quota
track.set_value(&Logger.track_value);
let _c1 = Logger.track_value.clone(); // | -> increase the Rc to 10 references, this will be the limit
track.set_value(&Logger.track_value);
for (k ,v) in Logger.mapped_messages.into_inner() {
println!("{:?}", (k ,v));
}
println!("{:?}", Logger.all_messages.into_inner());
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_module() {
#[derive(Clone, Debug)]
struct TestMs {
value: Rc<usize>,
ms: RefCell<Vec<String>>,
correct: Vec<String>,
}
impl Logger for TestMs {
fn warning(&self, message: &str) {
self.ms.borrow_mut().push(message.to_string());
}
fn info(&self, message: &str) {
self.ms.borrow_mut().push(message.to_string());
}
fn error(&self, message: &str) {
self.ms.borrow_mut().push(message.to_string());
}
}
let l = TestMs {
value: Rc::new(115),
ms: RefCell::new(vec![]),
correct: vec![
String::from("Info: you are using up too 40% of your quote"),
String::from("Warning: you have used up over 80% of your quota! Proceeds with precaution"),
String::from("Error: you are over your quota!")
],
};
let track = Tracker::new(&l, 5);
let _a = l.value.clone();
track.peek(&l.value); // 40%
let _a1 = l.value.clone();
let _a2 = l.value.clone();
track.set_value(&l.value); // 80%
let _a3 = l.value.clone();
track.set_value(&l.value); // 100%
for (i, v) in l.ms.into_inner().iter().enumerate() {
assert_eq!(v, &l.correct[i])
}
}
#[test]
fn test_module_usage_hasmap() {
let log = Worker::new(1000);
let track = Tracker::new(&log, 12);
let _clone_test = log.track_value.clone();
let _clone_test1 = log.track_value.clone();
let _clone_test2 = log.track_value.clone();
let _clone_test3 = log.track_value.clone();
let _clone_test4 = log.track_value.clone();
let _clone_test5 = log.track_value.clone();
let _clone_test6 = log.track_value.clone();
let _clone_test7 = log.track_value.clone();
// warning: 75% of the quota
track.set_value(&log.track_value);
assert_eq!(log.mapped_messages.borrow().get("Warning").unwrap(), "you have used up over 75% of your quota! Proceeds with precaution");
let _clone_test8 = log.track_value.clone();
// warning: 83% of the quota <- most resent of the messages last onw to be added to the hashmap
track.set_value(&log.track_value);
assert_eq!(log.mapped_messages.borrow().get("Warning").unwrap(), "you have used up over 83% of your quota! Proceeds with precaution");
// info: 83%
track.peek(&log.track_value);
assert_eq!(log.mapped_messages.borrow().get("Info").unwrap(), "you are using up too 83% of your quote");
let _clone_test9 = log.track_value.clone();
// info: 91%
track.peek(&log.track_value);
assert_eq!(log.mapped_messages.borrow().get("Info").unwrap(), "you are using up too 91% of your quote");
let _clone_test10 = log.track_value.clone();
// error: passed the quota
track.set_value(&log.track_value);
assert_eq!(log.mapped_messages.borrow().get("Error").unwrap(), "you are over your quota!");
}
#[test]
fn test_module_usage_vector() {
let correct = vec![
"Info: you are using up too 40% of your quote",
"Warning: you have used up over 80% of your quota! Proceeds with precaution",
"Info: you are using up too 80% of your quote", "Error: you are over your quota!"
];
let log = Worker::new(1);
let track = Tracker::new(&log, 5);
let _a = log.track_value.clone();
// info: 40%
track.peek(&log.track_value);
let _a1 = log.track_value.clone();
let _a2 = log.track_value.clone();
// warning: 80%
track.set_value(&log.track_value);
// info: 80%
track.peek(&log.track_value);
let _a3 = log.track_value.clone();
// error: passed the quota
track.set_value(&log.track_value);
for (i, v) in log.all_messages.into_inner().iter().enumerate() {
assert_eq!(v, correct[i]);
}
}
}

83
subjects/borrow_box/README.md

@ -0,0 +1,83 @@
## borrow box
### Instructions
You will have to create a **CRUD** functionality. Therefore creating the following functions :
- `new`, that receives two players and initializes them with a name and a score. This functions should
return the structure wrapped in a Box.
- `read_winner`, returns a tuple with the name and the score of the player who is winning.
In case none of the players are winning, it should return the same tuple with the string "Same score! tied" and the tied score.
- `update_score`, that receives the name of a player.
This function should increment the score of the player. The score should only be increased if it does not pass the `nbr_of_games`.
Example: if the nbr_of_games is 3 then the game should be best out of three. So if one play as 2 wins then
he is the winner and the function should not increase the score anymore for either players.
- `delete`, that takes the ownership of the boxed game and returning a string : "Game deleted: id -> 0".
### Expected Function
```rust
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Game {
// expected public fields
}
impl Game {
pub fn new(i: u32, pl1: String, pl2: String, n: u16) -> Box<Game> {}
pub fn read_winner(&self) -> (String, u16) {}
pub fn update_score(&mut self, user_name: String) {}
pub fn delete(self) -> String {}
}
```
### Usage
Here is a program to test your function
```rust
fn main() {
let mut game = Game::create_game(0, String::from("Joao"), String::from("Susana"), 5);
println!("{:?}", game.read_winner());
// output : ("Same score! tied", 0)
game.update_score(String::from("Joao"));
game.update_score(String::from("Joao"));
game.update_score(String::from("Susana"));
game.update_score(String::from("Susana"));
println!("{:?}", game.read_winner());
// output : ("Same score! tied", 2)
game.update_score(String::from("Joao"));
// this one will not count because it already 5 games played, the nbr_of_games
game.update_score(String::from("Susana"));
println!("{:?}", game.read_winner());
// output : ("Joao", 3)
game.delete();
println!("{:?}", game.delete());
// output : "game deleted: id -> 0"
// game.read_winner();
// this will give error
// because the game was dropped, no longer exists on the heap
}
```
And its output:
```console
student@ubuntu:~/[[ROOT]]/test$ cargo run
("Same score! tied", 0)
("Same score! tied", 2)
("Joao", 3)
"game deleted: id -> 0"
student@ubuntu:~/[[ROOT]]/test$
```
### Notions
- https://doc.rust-lang.org/book/ch15-01-box.html

53
subjects/box_it/README.md

@ -0,0 +1,53 @@
## box_it
### Instructions
Create the following functions:
- `transform_and_save_on_heap`, that receives a string with a number (that can or not have a k (kilo) suffix)
and transforms those numbers into `u32` and inserts it into a vector that must be saved in the heap using **Box**.
- `take_value_ownership`, that takes the value (unboxed value) form the box and returns it
### Expected Function
```rust
pub fn transform_and_save_on_heap(s: String) -> Box<Vec<u32>> {}
pub fn take_value_ownership(a: Box<Vec<u32>>) -> Vec<u32> {}
```
### Usage
Here is a program to test your function
```rust
fn main() {
let new_str = String::from("5.5k 8.9k 32");
// creating a variable and we save it in the Heap
let a_h = transform_and_save_on_heap(new_str);
println!("Box value : {:?}", &a_h);
println!("size occupied in the stack : {:?} bytes", (std::mem::size_of_val(&a_h)));
let a_b_v = take_value_ownership(a_h);
println!("value : {:?}", &a_b_v);
println!("size occupied in the stack : {:?} bytes", (std::mem::size_of_val(&a_b_v)));
// whenever the box, in this case "a_h", goes out of scope it will be deallocated, freed
}
```
And its output:
```console
student@ubuntu:~/[[ROOT]]/test$ cargo run
Box value : [6800, 13500]
size occupied in the stack : 8 bytes
value : [6800, 13500]
size occupied in the stack : 24 bytes
student@ubuntu:~/[[ROOT]]/test$
```
### Notions
- https://doc.rust-lang.org/book/ch15-00-smart-pointers.html
- https://doc.rust-lang.org/book/ch15-01-box.html

79
subjects/box_recursion/README.md

@ -0,0 +1,79 @@
## box_recursion
### Instructions
Using the given code create the following functions:
- `new` that will initialize the `WorkEnvironment` as `None`
- `add_worker`, that receives two strings, one being the type of worker and the other the name of the worker.
- `remove_worker`, that removes the last worker that was placed in the `WorkEnvironment`, this functions should
return a `Option` with the name of the worker.
- `search_worker`, that return a tuple with the name and type of worker.
You must also create a type called `Link` this will be the connection of the structures `WorkEnvironment` and `Worker`.
Do not forget that this will be a recursion type and it must point to `None` if there is no workers.
### Expected Function
```rust
pub struct WorkEnvironment {
pub grade: Link,
}
pub type Link =
pub struct Worker {
pub worker_type: String,
pub worker_name: String,
pub next_worker: Link,
}
impl WorkEnvironment {
pub fn new() -> WorkEnvironment {}
pub fn add_worker(&mut self, t: String, name: String) {}
pub fn remove_worker(&mut self) -> Option<String> {}
pub fn search_worker(&self) -> Option<(String, String)> {}
}
```
### Usage
Here is a program to test your function
```rust
fn main() {
let mut list = WorkEnvironment::new();
list.add_worker(String::from("CEO"), String::from("Marie"));
list.add_worker(String::from("Manager"), String::from("Monica"));
list.add_worker(String::from("Normal Worker"), String::from("Ana"));
list.add_worker(String::from("Normal Worker"), String::from("Alice"));
println!("{:?}", list);
println!("{:?}", list.search_worker());
list.remove_worker();
list.remove_worker();
list.remove_worker();
list.remove_worker();
println!("{:?}", list);
}
```
And its output:
```console
student@ubuntu:~/[[ROOT]]/test$ cargo run
WorkEnvironment { grade: Some(Worker { worker_type: "Normal Worker", worker_name: "Alice", next_worker: Some(Worker { worker_type: "Normal Worker", worker_name: "Ana", next_worker: Some(Worker { worker_type: "Manager", worker_name: "Monica", next_worker: Some(Worker { worker_type: "CEO", worker_name: "Marie", next_worker: None }) }) }) }) }
Some(("Alice", "Normal Worker"))
WorkEnvironment { grade: None }
student@ubuntu:~/[[ROOT]]/test$
```
### Notions
- https://doc.rust-lang.org/rust-by-example/custom_types/enum.html
- https://doc.rust-lang.org/book/ch15-01-box.html
- https://doc.rust-lang.org/std/option/
- https://doc.rust-lang.org/book/ch15-01-box.html

109
subjects/drop_the_thread/README.md

@ -0,0 +1,109 @@
## drop_the_thread
### Instructions
"Interior mutability is a design pattern in Rust that allows you to mutate data even when there are immutable references to that data"
You must create a Drop checker API. For this you must create:
- Two structures:
- `Workers` that will have two fields:
- `drops` that will save the number of dropped threads
- `states` that will save a state of multiple threads.
If the thread is not dropped, the state will be false otherwise true.
- `Thread` that will have the following fields:
- `pid`, the id of the thread
- `cmd`, the name of the thread
- `parent`, that will be the link to the structure `Workers` (Tip: this must be a reference to the structure Workers)
- Implementation of each structure:
- `Workers` :
- `new`, that creates a default worker
- `new_worker`, that returns a tuple with the `pid` and a new `Thread`,
this function must receive a `String` being the `cmd`
- `is_dropped`, that receives a `pid` and returns a `bool` that indicates the state of the thread by using the `pid`
- `track_worker`, it should return a `usize`, that will be the last available index of the `states` vector, being the new next thread
- `add_drop`, this function must be **called by the `Drop` trait**. It will receive a `pid` that will be used to change the
state of the thread. If the state of that thread is `true` then it will panic with the message ("Cannot drop {}, because its already dropped", pid).
Otherwise it should change the state to true and increment the `drops` field by one.
- `Thread`:
- `new_thread`, that initializes a new thread
- `skill`, that drops the thread
- You must implement for the structure `Thread` the `Drop` trait. In this trait you must call the function `add_drop` so that the state of the thread changes
### Expected Function
```rust
use std::cell::{RefCell, Cell};
#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub struct Workers {
pub drops: Cell<usize>,
pub state: RefCell<Vec<bool>>
}
impl Workers {
pub fn new() -> Workers {}
pub fn new_worker(&self, c: String) -> (usize, Thread) {}
pub fn track_worker(&self) -> usize {}
pub fn is_dropped(&self, id: usize) -> bool {}
pub fn add_drop(&self, id: usize) {}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Thread<'a> {
// expected public fields
}
impl<'a> Thread<'a> {
pub fn new_thread(p: usize, c: String, t: &'a Workers) -> Thread {}
pub fn skill(self) {}
}
```
### Usage
Here is a program to test your function
```rust
use std::rc::Rc;
fn main() {
let worker = Workers::new();
let (id, thread) = worker.new_worker(String::from("command"));
let (id1, thread1) = worker.new_worker(String::from("command1"));
thread.skill();
println!("{:?}", (worker.is_dropped(id), id, &worker.drops));
thread1.skill();
println!("{:?}", (worker.is_dropped(id1), id1, &worker.drops));
let (id2, thread2) = worker.new_worker(String::from("command2"));
let thread2 = Rc::new(thread2);
let thread2_clone = thread2.clone();
drop(thread2_clone);
println!("{:?}", (worker.is_dropped(id2), id2, &worker.drops, Rc::strong_count(&thread2)));
}
```
And its output:
```console
student@ubuntu:~/[[ROOT]]/test$ cargo run
(true, 0, Cell { value: 1 })
(true, 1, Cell { value: 2 })
(false, 2, Cell { value: 2 }, 1)
student@ubuntu:~/[[ROOT]]/test$
```
### Notions
- https://doc.bccnsoft.com/docs/rust-1.36.0-docs-html/std/ops/trait.Drop.html
- https://doc.rust-lang.org/std/cell/struct.RefCell.html
- https://doc.rust-lang.org/book/ch15-05-interior-mutability.html

78
subjects/how_many_references/README.md

@ -0,0 +1,78 @@
## how many references
### Instructions
Create the following functions :
- `add_ele` that adds an element to the value in the `Node`
- `how_many_references` that returns how many times the value is referenced in the code
- `rm_all_ref` that receives a `Rc<String>` and removes all elements from the vector that
are equal to that value, this should only happen if the two Rcs point to the same allocation
### Expected Function
```rust
pub use std::rc::Rc;
pub struct Node {
pub value: Vec<Rc<String>>,
}
impl Node {
pub fn new(value: Vec<Rc<String>>) -> Node {
Node { value: value }
}
pub fn add_ele(&mut self, v: Rc<String>) {}
pub fn rm_all_ref(&mut self, v: Rc<String>) {}
}
pub fn how_many_references(value: &Rc<String>) -> usize {}
```
### Usage
Here is a program to test your function
```rust
fn main() {
let a = Rc::new(String::from("a"));
let b = Rc::new(String::from("b"));
let c = Rc::new(String::from("c"));
let a1 = Rc::new(String::from("a"));
let mut new_node = Node::new(vec![a.clone()]);
new_node.add_ele(b.clone());
new_node.add_ele(a.clone());
new_node.add_ele(c.clone());
new_node.add_ele(a.clone());
println!("a: {:?}", how_many_references(&a));
println!("b: {:?}", how_many_references(&b));
println!("c: {:?}", how_many_references(&c));
new_node.rm_all_ref(a1.clone());
new_node.rm_all_ref(a.clone());
println!("a: {:?}", how_many_references(&a));
println!("b: {:?}", how_many_references(&b));
println!("c: {:?}", how_many_references(&c));
}
```
And its output:
```console
student@ubuntu:~/[[ROOT]]/test$ cargo run
a: 4
b: 2
c: 2
a: 1
b: 2
c: 2
student@ubuntu:~/[[ROOT]]/test$
```
### Notions
- https://doc.rust-lang.org/book/ch15-04-rc.html
- https://doc.rust-lang.org/std/rc/struct.Rc.html

112
subjects/ref_cell/README.md

@ -0,0 +1,112 @@
## ref_cell
### Instructions
### 1º part
Create a module called `messenger`. This module will be able to inform a user of how much references of a given value he is using.
The main objective for this module is to limit how many times a value is referenced.
For the module you must create the following:
- A trait `Logger` that implements three functions: `warning`, `info`, `error`. All function should receive a reference to themselves and a string literal.
```rust
fn warning(&self, msg: &str);
fn info(&self, msg: &str);
fn error(&self, msg: &str);
```
- A structure called `Tracker`, that must have the fields: `logger` being a reference to the `Logger`, `value` being the count of how many times the value was referenced,
`max` being the max count of references the actual value can achieve.
- An implementation of three functions that are associated to the `Tracker` structure:
- `new` that will initialize the structure
- `set_value` that sets the value to the `Tracker` structure and writes to the trait functions. This should be done comparing the **max** and the number of referenced of the actual value.
If the percentage is equal or greater to 100% of the limit usage, it should write **"Error: you are over your quota!"** to the `error` function
If the percentage is equal or greater to 70% of the limit usage, it should write **("Warning: you have used up over {}% of your quota! Proceeds with precaution", <calculated_percentage>)** to the `warning` function
- `peek` that will take a peek of how much usage the variable already has. It should write **("Info: you are using up too {}% of your quote", <calculated_percentage>)** to the `info` function
### 2ª part
Afterwards you must use the module `messenger` and create the following:
- A structure `Worker` that has the fields:
- `track_value` this will be the value that will be tracked by the tracker.
- `mapped_messages` that will have the latest messages. This must be a HashMap with the key being the type of message
sent by the logger (info, error or warning) and the value being the message
- `all_messages` that will be a vector of all messages sent.
- A `new` function that initializes the structure `Worker`
- To use the trait `Logger` you must implement it for the Worker structure. Each function (warning, error and info) must insert the message to the
respective fields of the structure Worker.
You must use **interior mutability**, this means it must be able to mutate data even when there are immutable references to that data.
So the user doesn't need to use the keyword `mut` (tip: RefCell)
### Usage
Here is a program to test your function
```rust
fn main() {
// initialize the worker
let Logger = Worker::new(1);
// initialize the tracker, with the max number of
// called references as 10
let track = Tracker::new(&Logger, 10);
let _a = Logger.track_value.clone(); // |\
let _a1 = Logger.track_value.clone(); // | -> increase the Rc to 4 references
let _a2 = Logger.track_value.clone(); // |/
// take a peek of how much we already used from our quota
track.peek(&Logger.track_value);
let _b = Logger.track_value.clone(); // |\
let _b1 = Logger.track_value.clone(); // | -> increase the Rc to 8 references
let _b2 = Logger.track_value.clone(); // | /
let _b3 = Logger.track_value.clone(); // |/
// this will set the value and making a verification of
// how much we already used of our quota
track.set_value(&Logger.track_value);
let _c = Logger.track_value.clone(); // | -> increase the Rc to 9 references
// this will set the value and making a verification of
// how much we already used of our quota
track.set_value(&Logger.track_value);
let _c1 = Logger.track_value.clone(); // | -> increase the Rc to 10 references, this will be the limit
track.set_value(&Logger.track_value);
for (k ,v) in Logger.mapped_messages.into_inner() {
println!("{:?}", (k ,v));
}
println!("{:?}", Logger.all_messages.into_inner());
}
```
And its output:
```console
student@ubuntu:~/[[ROOT]]/test$ cargo run
("Info", "you are using up too 40% of your quote")
("Warning", "you have used up over 90% of your quota! Proceeds with precaution")
("Error", "you are over your quota!")
[
"Info: you are using up too 40% of your quote",
"Warning: you have used up over 80% of your quota! Proceeds with precaution",
"Warning: you have used up over 90% of your quota! Proceeds with precaution",
"Error: you are over your quota!"
]
student@ubuntu:~/[[ROOT]]/test$
```
### Notions
- https://doc.rust-lang.org/std/cell/struct.RefCell.html
- https://doc.rust-lang.org/std/rc/struct.Rc.html
Loading…
Cancel
Save