-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
48e1770
commit 3ea156e
Showing
7 changed files
with
343 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
use std::error::Error; | ||
use std::fmt; | ||
|
||
// Custom error type | ||
#[derive(Debug)] | ||
pub enum CalculationError { | ||
DivisionByZero, | ||
Overflow, | ||
InvalidInput(String), | ||
} | ||
|
||
// Implement Display for our error type | ||
impl fmt::Display for CalculationError { | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
match self { | ||
CalculationError::DivisionByZero => write!(f, "division by zero"), | ||
CalculationError::Overflow => write!(f, "calculation overflow"), | ||
CalculationError::InvalidInput(msg) => write!(f, "invalid input: {}", msg), | ||
} | ||
} | ||
} | ||
|
||
// Implement the Error trait | ||
impl Error for CalculationError {} | ||
|
||
// Function that uses our custom error type | ||
fn divide(a: i32, b: i32) -> Result<i32, CalculationError> { | ||
if b == 0 { | ||
return Err(CalculationError::DivisionByZero); | ||
} | ||
|
||
if a == i32::MIN && b == -1 { | ||
return Err(CalculationError::Overflow); | ||
} | ||
|
||
Ok(a / b) | ||
} | ||
|
||
pub fn run() { | ||
println!("\nCustom Error Examples:"); | ||
|
||
// Test various scenarios | ||
let test_cases = vec![ | ||
(10, 2), | ||
(10, 0), | ||
(i32::MIN, -1), | ||
]; | ||
|
||
for (a, b) in test_cases { | ||
match divide(a, b) { | ||
Ok(result) => println!("{} / {} = {}", a, b, result), | ||
Err(e) => println!("Error: {}", e), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
use std::fs::File; | ||
use std::io::{self, Read}; | ||
|
||
pub fn run() { | ||
println!("\nError Handling Examples:"); | ||
|
||
// Example 1: Basic error handling with match | ||
match read_username_from_file("username.txt") { | ||
Ok(username) => println!("Username: {}", username), | ||
Err(e) => println!("Error reading username: {}", e), | ||
} | ||
|
||
// Example 2: Using the ? operator | ||
if let Err(e) = read_username_concise("username.txt") { | ||
println!("Error reading username (concise): {}", e); | ||
} | ||
|
||
// Example 3: Demonstrating panic | ||
demonstrate_panic(); | ||
} | ||
|
||
// Example function that returns a Result | ||
fn read_username_from_file(filename: &str) -> Result<String, io::Error> { | ||
let mut file = match File::open(filename) { | ||
Ok(file) => file, | ||
Err(e) => return Err(e), | ||
}; | ||
|
||
let mut username = String::new(); | ||
match file.read_to_string(&mut username) { | ||
Ok(_) => Ok(username), | ||
Err(e) => Err(e), | ||
} | ||
} | ||
|
||
// Same function using the ? operator for more concise error handling | ||
fn read_username_concise(filename: &str) -> Result<String, io::Error> { | ||
let mut username = String::new(); | ||
File::open(filename)?.read_to_string(&mut username)?; | ||
Ok(username) | ||
} | ||
|
||
// Function demonstrating when to use panic! | ||
fn demonstrate_panic() { | ||
let names = vec!["Alice", "Bob", "Charlie"]; | ||
|
||
// Safe access | ||
if let Some(name) = names.get(1) { | ||
println!("Safely accessed name: {}", name); | ||
} | ||
|
||
// This would panic - uncomment to see | ||
// let name = &names[5]; // This will panic! | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
pub fn run() { | ||
println!("\nIntegration Tests Example"); | ||
println!("(See tests directory for integration tests)"); | ||
} | ||
|
||
// Public API to be tested in integration tests | ||
pub struct Calculator { | ||
value: i32, | ||
} | ||
|
||
impl Calculator { | ||
pub fn new() -> Self { | ||
Calculator { value: 0 } | ||
} | ||
|
||
pub fn add(&mut self, x: i32) { | ||
self.value += x; | ||
} | ||
|
||
pub fn subtract(&mut self, x: i32) { | ||
self.value -= x; | ||
} | ||
|
||
pub fn get_value(&self) -> i32 { | ||
self.value | ||
} | ||
} | ||
|
||
// Note: Integration tests should be placed in the tests directory | ||
// Create a file: tests/calculator_tests.rs with the following content: | ||
/* | ||
use your_crate_name::Calculator; | ||
#[test] | ||
fn test_calculator_integration() { | ||
let mut calc = Calculator::new(); | ||
calc.add(5); | ||
calc.subtract(2); | ||
assert_eq!(calc.get_value(), 3); | ||
} | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
pub mod error_handling; | ||
pub mod custom_errors; | ||
pub mod result_option; | ||
pub mod testing; | ||
pub mod test_organization; | ||
pub mod integration_tests; | ||
|
||
pub fn run() { | ||
println!("Days 25-27: Error Handling and Testing"); | ||
error_handling::run(); | ||
custom_errors::run(); | ||
result_option::run(); | ||
testing::run(); | ||
test_organization::run(); | ||
integration_tests::run(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
pub fn run() { | ||
println!("\nResult and Option Examples:"); | ||
|
||
// Option examples | ||
demonstrate_option(); | ||
|
||
// Result examples | ||
demonstrate_result(); | ||
|
||
// Combining Option and Result | ||
demonstrate_combined(); | ||
} | ||
|
||
fn demonstrate_option() { | ||
println!("\nOption Examples:"); | ||
|
||
let numbers = vec![1, 2, 3, 4, 5]; | ||
|
||
// Using map with Option | ||
let first: Option<&i32> = numbers.first(); | ||
let plus_one: Option<i32> = first.map(|n| n + 1); | ||
println!("First number plus one: {:?}", plus_one); | ||
|
||
// Using and_then | ||
let maybe_string = Some("Hello"); | ||
let maybe_len = maybe_string.and_then(|s| Some(s.len())); | ||
println!("String length: {:?}", maybe_len); | ||
|
||
// Using filter | ||
let even_first = first.filter(|n| *n % 2 == 0); | ||
println!("First even number: {:?}", even_first); | ||
} | ||
|
||
fn demonstrate_result() { | ||
println!("\nResult Examples:"); | ||
|
||
// Chaining Results | ||
let result = parse_and_multiply("5") | ||
.and_then(|n| multiply_by_two(n)) | ||
.map_err(|e| format!("Calculation error: {}", e)); | ||
|
||
println!("Result of calculation: {:?}", result); | ||
} | ||
|
||
fn demonstrate_combined() { | ||
println!("\nCombined Option and Result Examples:"); | ||
|
||
let numbers = vec![1, 2, 3, 4, 5]; | ||
let index = 2; | ||
|
||
let result = get_number(&numbers, index) | ||
.ok_or_else(|| "Index out of bounds".to_string()) | ||
.and_then(|n| multiply_by_two(n)); | ||
|
||
match result { | ||
Ok(n) => println!("Number at index {} multiplied by 2: {}", index, n), | ||
Err(e) => println!("Error: {}", e), | ||
} | ||
} | ||
|
||
// Helper functions | ||
fn parse_and_multiply(s: &str) -> Result<i32, String> { | ||
s.parse::<i32>() | ||
.map_err(|e| e.to_string()) | ||
.map(|n| n * 2) | ||
} | ||
|
||
fn multiply_by_two(n: i32) -> Result<i32, String> { | ||
if n > i32::MAX / 2 { | ||
Err("Overflow would occur".to_string()) | ||
} else { | ||
Ok(n * 2) | ||
} | ||
} | ||
|
||
fn get_number(numbers: &[i32], index: usize) -> Option<i32> { | ||
numbers.get(index).copied() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
pub fn run() { | ||
println!("\nTest Organization Examples (see test modules below)"); | ||
} | ||
|
||
// Public function to test | ||
pub fn process_data(data: &str) -> Result<String, String> { | ||
// Call private helper function | ||
let processed = internal_process(data)?; | ||
Ok(processed) | ||
} | ||
|
||
// Private helper function | ||
fn internal_process(data: &str) -> Result<String, String> { | ||
if data.is_empty() { | ||
return Err("Data cannot be empty".to_string()); | ||
} | ||
Ok(data.to_uppercase()) | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
// Test helper function | ||
fn setup_test_data() -> String { | ||
"test data".to_string() | ||
} | ||
|
||
#[test] | ||
fn test_process_data_success() { | ||
let data = setup_test_data(); | ||
assert!(process_data(&data).is_ok()); | ||
} | ||
|
||
#[test] | ||
fn test_process_data_empty() { | ||
assert!(process_data("").is_err()); | ||
} | ||
|
||
// Nested test module | ||
mod internal_tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn test_internal_process() { | ||
let result = internal_process("hello"); | ||
assert_eq!(result.unwrap(), "HELLO"); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
pub fn run() { | ||
println!("\nTesting Examples (see test cases below)"); | ||
} | ||
|
||
pub fn add(a: i32, b: i32) -> i32 { | ||
a + b | ||
} | ||
|
||
pub fn divide(a: i32, b: i32) -> Option<i32> { | ||
if b == 0 { | ||
None | ||
} else { | ||
Some(a / b) | ||
} | ||
} | ||
|
||
pub fn greet(name: &str) -> String { | ||
format!("Hello, {}!", name) | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn test_add() { | ||
assert_eq!(add(2, 2), 4); | ||
assert_eq!(add(-1, 1), 0); | ||
assert_eq!(add(0, 0), 0); | ||
} | ||
|
||
#[test] | ||
fn test_divide() { | ||
assert_eq!(divide(10, 2), Some(5)); | ||
assert_eq!(divide(3, 0), None); | ||
} | ||
|
||
#[test] | ||
fn test_greet() { | ||
assert_eq!(greet("Alice"), "Hello, Alice!"); | ||
assert_ne!(greet("Bob"), "Hi, Bob!"); | ||
} | ||
|
||
#[test] | ||
#[should_panic(expected = "panic message")] | ||
fn test_panic() { | ||
panic!("panic message"); | ||
} | ||
} |