Skip to content

Commit 3697cc4

Browse files
committed
Refactoring dos testes
1 parent a31d350 commit 3697cc4

File tree

1 file changed

+85
-92
lines changed

1 file changed

+85
-92
lines changed

src/stdlib/process.rs

Lines changed: 85 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,115 +1,108 @@
1-
use std::process::{Child, ExitStatus};
21
use std::io;
2+
use std::process::{Child, ExitStatus};
3+
#[cfg(not(windows))]
4+
use nix::{
5+
sys::signal::{self, Signal},
6+
unistd::Pid,
7+
};
38

49
pub struct Processo {
5-
processo: Child,
10+
pub processo: Child,
611
}
712

813
impl Processo {
14+
915
#[cfg(windows)]
1016
pub fn terminate(&mut self) -> io::Result<()> {
11-
// No Windows, .kill() já usa TerminateProcess, que é o comportamento
12-
// esperado para terminate() e kill() do Python nessa plataforma.
1317
self.processo.kill()
1418
}
1519

1620
#[cfg(not(windows))]
1721
pub fn terminate(&mut self) -> io::Result<()> {
18-
// Em sistemas POSIX (Linux, macOS), precisamos enviar SIGTERM manualmente.
19-
// O .kill() padrão do Rust enviaria SIGKILL, que é muito agressivo.
20-
21-
// 1. Pega o PID (Process ID) do processo filho.
2222
let pid = Pid::from_raw(self.processo.id() as i32);
23-
24-
// 2. Envia o sinal SIGTERM para o PID.
2523
match signal::kill(pid, Signal::SIGTERM) {
2624
Ok(_) => Ok(()),
27-
Err(e) => {
28-
// 3. Converte o erro da crate 'nix' para um erro padrão 'std::io::Error'.
29-
Err(io::Error::new(io::ErrorKind::Other, e))
30-
}
25+
Err(e) => Err(io::Error::new(io::ErrorKind::Other, e)),
3126
}
32-
3327
}
34-
#[cfg(test)]
35-
mod tests {
36-
use super::*; // Importa tudo do módulo pai (Processo, etc.)
37-
use std::thread;
38-
use std::time::Duration;
39-
40-
#[test]
41-
fn test_process_creation_and_wait_success() {
42-
// Testa o caso mais básico: criar um processo que termina com sucesso.
43-
// O comando `sleep 0.1` é rápido e deve sair com código 0.
44-
let mut processo = Processo::new("sleep", &["0.1"]).expect("Falha ao criar processo 'sleep'");
45-
46-
let exit_code = processo.wait().expect("Falha ao esperar pelo processo");
47-
48-
// Assert: Verificamos se o código de saída é 0 (sucesso).
49-
assert_eq!(exit_code, 0);
50-
}
5128

52-
#[test]
53-
fn test_process_creation_fails_for_invalid_command() {
54-
// Testa se a criação falha quando o comando não existe.
55-
let resultado = Processo::new("comando_que_definitivamente_nao_existe_123", &[]);
56-
57-
// Assert: Verificamos que o resultado é um erro.
58-
assert!(resultado.is_err());
59-
}
29+
pub fn kill(&mut self) -> io::Result<()> {
30+
self.processo.kill()
31+
}
32+
33+
}
34+
mod tests {
35+
use super::*;
36+
use std::process::Command;
37+
use std::thread;
38+
use std::time::Duration;
6039

61-
#[test]
62-
fn test_terminate_long_running_process() {
63-
// 1. SETUP: Inicia um processo que demoraria muito para terminar sozinho.
64-
let mut processo = Processo::new("sleep", &["30"]).expect("Falha ao criar processo 'sleep 30'");
65-
// Dá um tempinho para o SO realmente iniciar o processo.
66-
thread::sleep(Duration::from_millis(100));
67-
68-
// 2. ACTION: Chama o método que queremos testar.
69-
processo.terminate().expect("Falha ao enviar sinal de terminate");
70-
71-
// 3. ASSERT: Verifica o resultado.
72-
let exit_code = processo.wait().expect("Falha ao esperar pelo processo terminado");
73-
74-
#[cfg(not(windows))]
75-
{
76-
// Em Linux/macOS, um processo terminado por sinal não tem um código de saída.
77-
// Nossa função wait() converte isso para -1. Esta é a verificação correta!
78-
assert_eq!(exit_code, -1, "Em POSIX, o código de saída de um processo terminado por sinal deve ser -1 (na nossa implementação)");
79-
}
80-
#[cfg(windows)]
81-
{
82-
// No Windows, TerminateProcess força um código de saída, que geralmente é 1.
83-
assert_eq!(exit_code, 1, "No Windows, o código de saída de um processo terminado geralmente é 1");
84-
}
40+
fn create_long_running_command() -> Command {
41+
if cfg!(windows) {
42+
let mut cmd = Command::new("timeout");
43+
cmd.arg("/T").arg("30");
44+
cmd
45+
} else {
46+
let mut cmd = Command::new("sleep");
47+
cmd.arg("30");
48+
cmd
8549
}
50+
}
8651

87-
#[test]
88-
fn test_kill_long_running_process() {
89-
// O teste para kill() é quase idêntico ao de terminate(),
90-
// pois ambos resultam em um encerramento anormal.
91-
92-
// 1. SETUP
93-
let mut processo = Processo::new("sleep", &["30"]).expect("Falha ao criar processo 'sleep 30'");
94-
thread::sleep(Duration::from_millis(100));
95-
96-
// 2. ACTION
97-
processo.kill().expect("Falha ao enviar sinal de kill");
98-
99-
// 3. ASSERT
100-
let exit_code = processo.wait().expect("Falha ao esperar pelo processo morto");
101-
102-
#[cfg(not(windows))]
103-
{
104-
// SIGKILL também resulta em um código de saída "None", que mapeamos para -1.
105-
assert_eq!(exit_code, -1, "Em POSIX, o código de saída de um processo morto por sinal deve ser -1");
106-
}
107-
#[cfg(windows)]
108-
{
109-
// O comportamento é o mesmo de terminate() no Windows.
110-
assert_eq!(exit_code, 1, "No Windows, o código de saída de um processo morto geralmente é 1");
111-
}
112-
}
113-
}
114-
52+
#[test]
53+
fn test_terminate_a_running_process() {
54+
let child = create_long_running_command()
55+
.spawn()
56+
.expect("Falha ao iniciar processo para o teste de terminate");
57+
58+
let mut processo = Processo { processo: child };
59+
60+
thread::sleep(Duration::from_millis(100));
61+
62+
processo.terminate().expect("Falha ao chamar terminate");
63+
64+
let exit_code = processo.wait().expect("Falha ao esperar pelo processo terminado");
65+
66+
let expected_code = if cfg!(windows) { 1 } else { -1 };
67+
assert_eq!(exit_code, expected_code, "O código de saída após terminate não foi o esperado.");
68+
}
69+
70+
#[test]
71+
fn test_kill_a_running_process() {
72+
let child = create_long_running_command()
73+
.spawn()
74+
.expect("Falha ao iniciar processo para o teste de kill");
75+
76+
77+
let mut processo = Processo { processo: child };
78+
79+
thread::sleep(Duration::from_millis(100));
80+
81+
processo.kill().expect("Falha ao chamar kill");
82+
83+
84+
let exit_code = processo.wait().expect("Falha ao esperar pelo processo morto");
85+
86+
let expected_code = if cfg!(windows) { 1 } else { -1 };
87+
assert_eq!(exit_code, expected_code, "O código de saída após kill não foi o esperado.");
88+
}
89+
90+
#[test]
91+
fn test_wait_on_a_process_that_finishes_normally() {
92+
let mut command = if cfg!(windows) {
93+
let mut cmd = Command::new("timeout");
94+
cmd.arg("/T").arg("1");
95+
cmd
96+
} else {
97+
let mut cmd = Command::new("sleep");
98+
cmd.arg("1");
99+
cmd
100+
};
101+
102+
let child = command.spawn().expect("Falha ao iniciar processo curto");
103+
let mut processo = Processo { processo: child };
104+
105+
let exit_code = processo.wait().expect("Falha ao esperar pelo processo");
106+
assert_eq!(exit_code, 0);
107+
}
115108
}

0 commit comments

Comments
 (0)