Quellcode durchsuchen

Added some tests. Removed valuable code.

themultiplexer vor 8 Jahren
Ursprung
Commit
64a0359b3e

+ 27
- 16
hw6/task1/src/main.rs Datei anzeigen

@@ -4,12 +4,13 @@ use std::process;
4 4
 extern crate nix;
5 5
 
6 6
 use nix::unistd::{fork, pipe, read, write};
7
-use nix::sys::wait::wait;
7
+use nix::sys::wait::{wait, WaitStatus};
8 8
 use std::str;
9
-use nix::sys::wait::WaitStatus;
10 9
 use nix::unistd::ForkResult::{Child, Parent};
11 10
 use std::os::unix::io::RawFd;
12 11
 
12
+mod unit_test_pipe;
13
+
13 14
 const BUFFER_SIZE: usize = 256;
14 15
 
15 16
 
@@ -33,16 +34,23 @@ fn main() {
33 34
                                 Ok(Child) => {
34 35
                                     match sum_strings(vec) {
35 36
                                         Ok(res) => println!("Sum = {}", res),
36
-                                        Err(e) => println!("{}", e),
37
+                                        Err(e) => {
38
+                                            println!("{}", e);
39
+                                            process::exit(1);
40
+                                        }
37 41
                                     }
38 42
                                 }
39 43
                                 Ok(Parent { .. }) => {
40 44
                                     if let Ok(ws) = wait() {
41
-                                        if let WaitStatus::Exited(_, _) = ws {
45
+                                        if let WaitStatus::Exited(_, exit_code) = ws {
42 46
                                             match mul_strings(vec) {
43 47
                                                 Ok(res) => println!("Mul = {}", res),
44
-                                                Err(e) => println!("{}", e),
48
+                                                Err(e) => {
49
+                                                    println!("{}", e);
50
+                                                    process::exit(1);
51
+                                                }
45 52
                                             }
53
+                                            process::exit(exit_code as i32);
46 54
                                         }
47 55
                                     }
48 56
                                 }
@@ -59,13 +67,16 @@ fn main() {
59 67
                     for s in numbers {
60 68
                         args = concatenate_strings(&args, &concatenate_strings(&s, " "));
61 69
                     }
62
-                    println!("sending to children: {}", args);
70
+                    println!("sending to childs: {}", args);
71
+
63 72
                     if let Err(_) = write(writer, args.as_bytes()) {
64 73
                         println!("Broken pipe")
65 74
                     }
66 75
 
67
-                    if let Err(_) = wait() {
68
-                        println!("Waiting on children failed")
76
+                    if let Ok(ws) = wait() {
77
+                        if let WaitStatus::Exited(_, exit_code) = ws {
78
+                            process::exit(exit_code as i32);
79
+                        }
69 80
                     }
70 81
                 }
71 82
 
@@ -106,12 +117,12 @@ fn split_into_strings<'a>(s1: &'a str) -> Vec<String> {
106 117
 }
107 118
 
108 119
 /// Calculates the sum of the given Strings and returns them as a Result.
109
-fn sum_strings(v: Vec<String>) -> Result<i32, String> {
110
-    let mut sum = 0;
120
+fn sum_strings(v: Vec<String>) -> Result<i64, String> {
121
+    let mut sum: i64 = 0;
111 122
     for x in v {
112
-        match x.parse::<i32>() {
123
+        match x.parse::<i64>() {
113 124
             Ok(val) => {
114
-                match i32::checked_add(sum, val) {
125
+                match i64::checked_add(sum, val) {
115 126
                     Some(y) => {
116 127
                         sum = y;
117 128
                     }
@@ -125,12 +136,12 @@ fn sum_strings(v: Vec<String>) -> Result<i32, String> {
125 136
 }
126 137
 
127 138
 /// Calculates the product of the given Strings and returns them as a Result.
128
-fn mul_strings(v: Vec<String>) -> Result<i32, String> {
129
-    let mut prod = 1;
139
+fn mul_strings(v: Vec<String>) -> Result<i64, String> {
140
+    let mut prod: i64 = 1;
130 141
     for x in v {
131
-        match x.parse::<i32>() {
142
+        match x.parse::<i64>() {
132 143
             Ok(val) => {
133
-                match i32::checked_mul(prod, val) {
144
+                match i64::checked_mul(prod, val) {
134 145
                     Some(y) => {
135 146
                         prod = y;
136 147
                     }

+ 24
- 0
hw6/task1/src/unit_test_pipe.rs Datei anzeigen

@@ -0,0 +1,24 @@
1
+#[cfg(test)]
2
+mod test {
3
+    use read_from_pipe;
4
+    use nix::unistd::{pipe, write};
5
+
6
+    #[test]
7
+    fn test_pipe() {
8
+        match pipe() {
9
+            Ok((reader, writer)) => {
10
+                let input = b"teststring";
11
+
12
+                if let Err(_) = write(writer, input) {
13
+                    // Broken pipe
14
+                }
15
+                assert_eq!(read_from_pipe(reader).unwrap(), "teststring".to_string());
16
+            }
17
+            Err(_) => {}
18
+        }
19
+
20
+    }
21
+
22
+    #[test]
23
+    fn test_kill_last_child() {}
24
+}

+ 5
- 1
hw6/task2/src/command.rs Datei anzeigen

@@ -2,12 +2,14 @@ use std::ffi::OsString;
2 2
 use std::str::FromStr;
3 3
 use std::env;
4 4
 
5
+#[derive(PartialEq, Debug)]
5 6
 pub enum Command {
6 7
     Empty,
7 8
     Exit,
8 9
     Cd(Option<OsString>),
9 10
 }
10 11
 
12
+#[derive(PartialEq, Debug)]
11 13
 pub struct CommandNotFoundError;
12 14
 
13 15
 impl FromStr for Command {
@@ -31,7 +33,8 @@ impl FromStr for Command {
31 33
 
32 34
 
33 35
 impl Command {
34
-    /// If the passed String exists, set the path of the Cd in the enum
36
+    /// If the passed String exists, set the path of the Cd in the enum (as OsString)
37
+    /// Returns **Command**
35 38
     pub fn parse_cd(cmd: Option<&str>) -> Self {
36 39
         match cmd {
37 40
             None => Command::Cd(None),
@@ -39,6 +42,7 @@ impl Command {
39 42
         }
40 43
     }
41 44
 
45
+    /// If this instance is of Kind **Command::Cd** either go to HOME or navigate to the given path
42 46
     pub fn exec_cd(&self) {
43 47
         if let Command::Cd(None) = *self {
44 48
             let possible_home = env::home_dir();

+ 4
- 5
hw6/task2/src/main.rs Datei anzeigen

@@ -1,19 +1,18 @@
1 1
 use std::process;
2
-use shell::{Shell, R, W};
2
+use shell::Shell;
3 3
 use std::io;
4 4
 
5
+mod unit_tests_shell;
5 6
 mod command;
6 7
 mod shell;
7 8
 
8 9
 
10
+
9 11
 fn main() {
10 12
     let stdin = io::stdin();
11
-    let input = R(stdin.lock());
12
-
13 13
     let stdout = io::stdout();
14
-    let output = W(stdout.lock());
15 14
 
16
-    let mut s = Shell::new(input, output, "schell".to_string());
15
+    let mut s = Shell::new(stdin.lock(), stdout.lock(), "schell".to_string());
17 16
     match s.start() {
18 17
         Ok(_) => process::exit(0),
19 18
         Err(_) => process::exit(1),

+ 8
- 46
hw6/task2/src/shell.rs Datei anzeigen

@@ -1,24 +1,18 @@
1
-use std::io::{BufRead, Write, Read, StdinLock, StdoutLock};
2
-use std::io;
3
-
1
+use std::io::{BufRead, Write};
4 2
 use command::*;
5 3
 use std::str::FromStr;
6 4
 use std::env;
7 5
 
8
-///Tuple-Structs which hold Std-in and -out locks.
9
-pub struct R<'a>(pub StdinLock<'a>);
10
-pub struct W<'a>(pub StdoutLock<'a>);
11
-
12
-pub struct Shell<R, W> {
6
+pub struct Shell<R: BufRead, W: Write> {
13 7
     pub reader: R,
14 8
     pub writer: W,
15 9
     pub should_exit: bool,
16 10
     pub name: String,
17 11
 }
18 12
 
19
-impl<'a> Shell<R<'a>, W<'a>> {
13
+impl<R: BufRead, W: Write> Shell<R, W> {
20 14
     /// Creates a new Shell with a name, input and output.
21
-    pub fn new(input: R<'a>, output: W<'a>, name: String) -> Self {
15
+    pub fn new(input: R, output: W, name: String) -> Self {
22 16
         Shell {
23 17
             reader: input,
24 18
             writer: output,
@@ -37,7 +31,7 @@ impl<'a> Shell<R<'a>, W<'a>> {
37 31
     /// If the Command-creation succeeds, run the command.
38 32
     fn shell_loop(&mut self) -> Result<(), &str> {
39 33
         while !self.should_exit {
40
-            if let Ok(line) = self.prompt() {
34
+            if let Ok(Some(line)) = self.prompt() {
41 35
                 let _ = Command::from_str(&line).and_then(|cmd| self.run(cmd));
42 36
             }
43 37
         }
@@ -46,7 +40,7 @@ impl<'a> Shell<R<'a>, W<'a>> {
46 40
 
47 41
     /// Prints the shell prompt.
48 42
     /// Waits for user input and returns the read line.
49
-    fn prompt(&mut self) -> Result<String, &str> {
43
+    pub fn prompt(&mut self) -> Result<Option<String>, &str> {
50 44
         match env::current_dir() {
51 45
             Ok(pwd) => {
52 46
                 let _ = self.writer.write(
@@ -58,8 +52,8 @@ impl<'a> Shell<R<'a>, W<'a>> {
58 52
                 let mut line: String = String::new();
59 53
                 let read_result = self.reader.read_line(&mut line);
60 54
                 match read_result {
61
-                    Ok(_) => Ok(line),
62
-                    Err(_) => Err("Error reading."),
55
+                    Ok(_) => Ok(Some(line)),
56
+                    Err(_) => Ok(None),
63 57
                 }
64 58
             }
65 59
             Err(_) => return Err("Path Error"),
@@ -80,35 +74,3 @@ impl<'a> Shell<R<'a>, W<'a>> {
80 74
         Ok(())
81 75
     }
82 76
 }
83
-
84
-/// Implement Read-Trait for Tuple-Struct R
85
-/// Simply calls `read` of StdinLock
86
-impl<'a> Read for R<'a> {
87
-    fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
88
-        self.0.read(buf)
89
-    }
90
-}
91
-
92
-/// Implement BufRead-Trait for Tuple-Struct R
93
-/// Simply calls `fill_buff` and `consume` from StdinLock
94
-impl<'a> BufRead for R<'a> {
95
-    fn fill_buf(&mut self) -> Result<&[u8], io::Error> {
96
-        self.0.fill_buf()
97
-    }
98
-
99
-    fn consume(&mut self, amt: usize) {
100
-        self.0.consume(amt)
101
-    }
102
-}
103
-
104
-/// Implement Write-Trait for Tuple-Struct W
105
-/// Simply calls `write` and `flush` from StdoutLock
106
-impl<'a> Write for W<'a> {
107
-    fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
108
-        self.0.write(buf)
109
-    }
110
-
111
-    fn flush(&mut self) -> Result<(), io::Error> {
112
-        self.0.flush()
113
-    }
114
-}

+ 41
- 1
hw6/task2/src/unit_tests_shell.rs Datei anzeigen

@@ -1,6 +1,46 @@
1 1
 #[cfg(test)]
2 2
 mod test {
3
-    use shell::Shell;
3
+    pub use shell::Shell;
4
+    use command::Command;
5
+    use command::CommandNotFoundError;
6
+    use std::str::FromStr;
7
+    use std::ffi::OsString;
8
+
9
+    #[test]
10
+    fn test_command_empty_whitespace() {
11
+        assert_eq!(Command::from_str("       ").unwrap(), Command::Empty);
12
+    }
13
+
14
+    #[test]
15
+    fn test_command_empty_tab() {
16
+        assert_eq!(Command::from_str("\t").unwrap(), Command::Empty);
17
+    }
18
+
19
+    #[test]
20
+    fn test_command_cd() {
21
+        assert_eq!(
22
+            Command::from_str("cd /home/peter/").unwrap(),
23
+            Command::Cd(Some(OsString::from("/home/peter/")))
24
+        );
25
+    }
26
+
27
+    #[test]
28
+    fn test_command_home() {
29
+        assert_eq!(Command::from_str("cd").unwrap(), Command::Cd(None));
30
+    }
31
+
32
+    #[test]
33
+    fn test_command_exit() {
34
+        assert_eq!(Command::from_str("exit").unwrap(), Command::Exit);
35
+    }
36
+
37
+    #[test]
38
+    fn test_command_not_found() {
39
+        assert_eq!(
40
+            Command::from_str("awdeiu33we").unwrap_err(),
41
+            CommandNotFoundError
42
+        );
43
+    }
4 44
 
5 45
     #[test]
6 46
     fn test_prompt_in_memory_with_string() {

Laden…
Abbrechen
Speichern