Skip to content
This repository was archived by the owner on Dec 15, 2025. It is now read-only.

Commit 2025a93

Browse files
committed
feat: Improve testapp and refine state transitions
- Refactor `testapp` module to improve code clarity and organization. - Improve the `State` transition logic for better error handling and state management. This prevents invalid state transitions. - Enhance error handling in `ZInitError` for better error reporting.
1 parent dd18c38 commit 2025a93

File tree

6 files changed

+72
-50
lines changed

6 files changed

+72
-50
lines changed

src/bin/testapp.rs

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
extern crate zinit;
22

33
use anyhow::Result;
4+
use std::env;
45
use std::path::Path;
56
use tokio::time::{sleep, Duration};
6-
use std::env;
77

88
use zinit::app::api::Client;
99
use zinit::testapp;
@@ -12,8 +12,16 @@ use zinit::testapp;
1212
async fn main() -> Result<()> {
1313
// Define paths for socket and config
1414
let temp_dir = env::temp_dir();
15-
let socket_path = temp_dir.join("zinit-test.sock").to_str().unwrap().to_string();
16-
let config_dir = temp_dir.join("zinit-test-config").to_str().unwrap().to_string();
15+
let socket_path = temp_dir
16+
.join("zinit-test.sock")
17+
.to_str()
18+
.unwrap()
19+
.to_string();
20+
let config_dir = temp_dir
21+
.join("zinit-test-config")
22+
.to_str()
23+
.unwrap()
24+
.to_string();
1725

1826
println!("Starting zinit with socket at: {}", socket_path);
1927
println!("Using config directory: {}", config_dir);
@@ -29,16 +37,22 @@ async fn main() -> Result<()> {
2937

3038
// Create service configurations
3139
println!("Creating service configurations...");
32-
40+
3341
// Create a find service
34-
testapp::create_service_config(&config_dir, "find-service", "find / -name \"*.txt\" -type f").await?;
35-
42+
testapp::create_service_config(
43+
&config_dir,
44+
"find-service",
45+
"find / -name \"*.txt\" -type f",
46+
)
47+
.await?;
48+
3649
// Create a sleep service with echo
3750
testapp::create_service_config(
38-
&config_dir,
39-
"sleep-service",
40-
"sh -c 'echo Starting sleep; sleep 30; echo Finished sleep'"
41-
).await?;
51+
&config_dir,
52+
"sleep-service",
53+
"sh -c 'echo Starting sleep; sleep 30; echo Finished sleep'",
54+
)
55+
.await?;
4256

4357
// Wait for zinit to load the configurations
4458
sleep(Duration::from_secs(1)).await;
@@ -58,7 +72,7 @@ async fn main() -> Result<()> {
5872
// Start the find service
5973
println!("\nStarting find-service...");
6074
client.start("find-service").await?;
61-
75+
6276
// Wait a bit and check status
6377
sleep(Duration::from_secs(2)).await;
6478
let status = client.status("find-service").await?;
@@ -67,7 +81,7 @@ async fn main() -> Result<()> {
6781
// Start the sleep service
6882
println!("\nStarting sleep-service...");
6983
client.start("sleep-service").await?;
70-
84+
7185
// Wait a bit and check status
7286
sleep(Duration::from_secs(2)).await;
7387
let status = client.status("sleep-service").await?;
@@ -76,7 +90,7 @@ async fn main() -> Result<()> {
7690
// Stop the find service
7791
println!("\nStopping find-service...");
7892
client.stop("find-service").await?;
79-
93+
8094
// Wait a bit and check status
8195
sleep(Duration::from_secs(2)).await;
8296
let status = client.status("find-service").await?;
@@ -85,15 +99,16 @@ async fn main() -> Result<()> {
8599
// Kill the sleep service with SIGTERM
86100
println!("\nKilling sleep-service with SIGTERM...");
87101
client.kill("sleep-service", "SIGTERM").await?;
88-
102+
89103
// Wait a bit and check status
90104
sleep(Duration::from_secs(2)).await;
91105
let status = client.status("sleep-service").await?;
92106
println!("sleep-service status after killing: {:?}", status);
93107

94108
// Cleanup - forget services
95109
println!("\nForgetting services...");
96-
if status.pid == 0 { // Only forget if it's not running
110+
if status.pid == 0 {
111+
// Only forget if it's not running
97112
client.forget("sleep-service").await?;
98113
}
99114
client.forget("find-service").await?;
@@ -104,4 +119,4 @@ async fn main() -> Result<()> {
104119

105120
println!("\nTest completed successfully!");
106121
Ok(())
107-
}
122+
}

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ extern crate tokio;
77

88
pub mod app;
99
pub mod manager;
10+
pub mod testapp;
1011
pub mod zinit;
11-
pub mod testapp;

src/testapp/mod.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use anyhow::Result;
2+
use std::env;
23
use std::path::Path;
4+
use std::process::Stdio;
35
use tokio::process::Command;
46
use tokio::time::{sleep, Duration};
5-
use std::process::Stdio;
6-
use std::env;
77

88
pub async fn start_zinit(socket_path: &str, config_dir: &str) -> Result<()> {
99
// Create a temporary config directory if it doesn't exist
@@ -27,12 +27,12 @@ pub async fn start_zinit(socket_path: &str, config_dir: &str) -> Result<()> {
2727
.stderr(Stdio::piped());
2828

2929
let child = cmd.spawn()?;
30-
30+
3131
// Give zinit some time to start up
3232
sleep(Duration::from_secs(1)).await;
33-
33+
3434
println!("Zinit started with PID: {:?}", child.id());
35-
35+
3636
Ok(())
3737
}
3838

@@ -54,4 +54,4 @@ dir: /
5454

5555
tokio::fs::write(config_path, config_content).await?;
5656
Ok(())
57-
}
57+
}

src/zinit/errors.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,22 @@ impl ZInitError {
5959

6060
/// Create a new InvalidStateTransition error
6161
pub fn invalid_state_transition<S: Into<String>>(message: S) -> Self {
62-
ZInitError::InvalidStateTransition { message: message.into() }
62+
ZInitError::InvalidStateTransition {
63+
message: message.into(),
64+
}
6365
}
6466

6567
/// Create a new DependencyError error
6668
pub fn dependency_error<S: Into<String>>(message: S) -> Self {
67-
ZInitError::DependencyError { message: message.into() }
69+
ZInitError::DependencyError {
70+
message: message.into(),
71+
}
6872
}
6973

7074
/// Create a new ProcessError error
7175
pub fn process_error<S: Into<String>>(message: S) -> Self {
72-
ZInitError::ProcessError { message: message.into() }
76+
ZInitError::ProcessError {
77+
message: message.into(),
78+
}
7379
}
74-
}
80+
}

src/zinit/state.rs

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,27 @@ pub enum Target {
1616
pub enum State {
1717
/// Service is in an unknown state
1818
Unknown,
19-
19+
2020
/// Blocked means one or more dependencies hasn't been met yet. Service can stay in
2121
/// this state as long as at least one dependency is not in either Running, or Success
2222
Blocked,
23-
23+
2424
/// Service has been started, but it didn't exit yet, or we didn't run the test command.
2525
Spawned,
26-
26+
2727
/// Service has been started, and test command passed.
2828
Running,
29-
29+
3030
/// Service has exited with success state, only one-shot can stay in this state
3131
Success,
32-
32+
3333
/// Service exited with this error, only one-shot can stay in this state
3434
Error(WaitStatus),
35-
35+
3636
/// The service test command failed, this might (or might not) be replaced
3737
/// with an Error state later on once the service process itself exits
3838
TestFailure,
39-
39+
4040
/// Failure means the service has failed to spawn in a way that retrying
4141
/// won't help, like command line parsing error or failed to fork
4242
Failure,
@@ -48,58 +48,59 @@ impl State {
4848
match (self, new_state) {
4949
// From Unknown state, any transition is valid
5050
(State::Unknown, _) => true,
51-
51+
5252
// From Blocked state
5353
(State::Blocked, State::Spawned) => true,
5454
(State::Blocked, State::Failure) => true,
55-
55+
5656
// From Spawned state
5757
(State::Spawned, State::Running) => true,
5858
(State::Spawned, State::TestFailure) => true,
5959
(State::Spawned, State::Error(_)) => true,
6060
(State::Spawned, State::Success) => true,
61-
61+
6262
// From Running state
6363
(State::Running, State::Success) => true,
6464
(State::Running, State::Error(_)) => true,
65-
65+
6666
// To Unknown or Blocked state is always valid
6767
(_, State::Unknown) => true,
6868
(_, State::Blocked) => true,
69-
69+
7070
// Any other transition is invalid
7171
_ => false,
7272
}
7373
}
74-
74+
7575
/// Attempt to transition to a new state, validating the transition
7676
pub fn transition_to(&self, new_state: State) -> Result<State, ZInitError> {
7777
if self.can_transition_to(&new_state) {
7878
Ok(new_state)
7979
} else {
80-
Err(ZInitError::invalid_state_transition(
81-
format!("Invalid transition from {:?} to {:?}", self, new_state)
82-
))
80+
Err(ZInitError::invalid_state_transition(format!(
81+
"Invalid transition from {:?} to {:?}",
82+
self, new_state
83+
)))
8384
}
8485
}
85-
86+
8687
/// Check if the state is considered "active" (running or in progress)
8788
pub fn is_active(&self) -> bool {
8889
matches!(self, State::Running | State::Spawned)
8990
}
90-
91+
9192
/// Check if the state is considered "terminal" (success or failure)
9293
pub fn is_terminal(&self) -> bool {
9394
matches!(self, State::Success | State::Error(_) | State::Failure)
9495
}
95-
96+
9697
/// Check if the state is considered "successful"
9798
pub fn is_successful(&self) -> bool {
9899
matches!(self, State::Success | State::Running)
99100
}
100-
101+
101102
/// Check if the state is considered "failed"
102103
pub fn is_failed(&self) -> bool {
103104
matches!(self, State::Error(_) | State::Failure | State::TestFailure)
104105
}
105-
}
106+
}

src/zinit/types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use nix::sys::wait::WaitStatus;
22
use std::collections::HashMap;
33
use std::sync::Arc;
4-
use tokio::sync::RwLock;
54
use tokio::sync::watch;
5+
use tokio::sync::RwLock;
66
use tokio_stream::wrappers::WatchStream;
77

88
/// Extension trait for WaitStatus to check if a process exited successfully
@@ -56,4 +56,4 @@ where
5656
pub fn watcher(&self) -> Watcher<T> {
5757
WatchStream::new(self.tx.subscribe())
5858
}
59-
}
59+
}

0 commit comments

Comments
 (0)