command-stream 0.9.1 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,207 @@
1
+ //! Integration tests for the state module
2
+
3
+ use command_stream::state::{GlobalState, ShellSettings};
4
+
5
+ #[test]
6
+ fn test_shell_settings_default() {
7
+ let settings = ShellSettings::new();
8
+ assert!(!settings.errexit);
9
+ assert!(!settings.verbose);
10
+ assert!(!settings.xtrace);
11
+ assert!(!settings.pipefail);
12
+ assert!(!settings.nounset);
13
+ assert!(!settings.noglob);
14
+ assert!(!settings.allexport);
15
+ }
16
+
17
+ #[test]
18
+ fn test_shell_settings_set_short_flags() {
19
+ let mut settings = ShellSettings::new();
20
+
21
+ settings.set("e", true);
22
+ assert!(settings.errexit);
23
+
24
+ settings.set("v", true);
25
+ assert!(settings.verbose);
26
+
27
+ settings.set("x", true);
28
+ assert!(settings.xtrace);
29
+
30
+ settings.set("u", true);
31
+ assert!(settings.nounset);
32
+
33
+ settings.set("f", true);
34
+ assert!(settings.noglob);
35
+
36
+ settings.set("a", true);
37
+ assert!(settings.allexport);
38
+ }
39
+
40
+ #[test]
41
+ fn test_shell_settings_set_long_names() {
42
+ let mut settings = ShellSettings::new();
43
+
44
+ settings.set("errexit", true);
45
+ assert!(settings.errexit);
46
+
47
+ settings.set("verbose", true);
48
+ assert!(settings.verbose);
49
+
50
+ settings.set("xtrace", true);
51
+ assert!(settings.xtrace);
52
+
53
+ settings.set("nounset", true);
54
+ assert!(settings.nounset);
55
+
56
+ settings.set("pipefail", true);
57
+ assert!(settings.pipefail);
58
+ }
59
+
60
+ #[test]
61
+ fn test_shell_settings_enable_disable() {
62
+ let mut settings = ShellSettings::new();
63
+
64
+ settings.enable("errexit");
65
+ assert!(settings.errexit);
66
+
67
+ settings.disable("errexit");
68
+ assert!(!settings.errexit);
69
+ }
70
+
71
+ #[test]
72
+ fn test_shell_settings_reset() {
73
+ let mut settings = ShellSettings::new();
74
+
75
+ settings.enable("errexit");
76
+ settings.enable("verbose");
77
+ settings.enable("pipefail");
78
+
79
+ settings.reset();
80
+
81
+ assert!(!settings.errexit);
82
+ assert!(!settings.verbose);
83
+ assert!(!settings.pipefail);
84
+ }
85
+
86
+ #[tokio::test]
87
+ async fn test_global_state_shell_settings() {
88
+ let state = GlobalState::new();
89
+
90
+ // Default settings
91
+ let settings = state.get_shell_settings().await;
92
+ assert!(!settings.errexit);
93
+
94
+ // Enable option
95
+ state.enable_shell_option("errexit").await;
96
+ let settings = state.get_shell_settings().await;
97
+ assert!(settings.errexit);
98
+
99
+ // Disable option
100
+ state.disable_shell_option("errexit").await;
101
+ let settings = state.get_shell_settings().await;
102
+ assert!(!settings.errexit);
103
+ }
104
+
105
+ #[tokio::test]
106
+ async fn test_global_state_runner_registration() {
107
+ let state = GlobalState::new();
108
+
109
+ assert_eq!(state.active_runner_count().await, 0);
110
+
111
+ let id1 = state.register_runner().await;
112
+ assert_eq!(state.active_runner_count().await, 1);
113
+
114
+ let id2 = state.register_runner().await;
115
+ assert_eq!(state.active_runner_count().await, 2);
116
+
117
+ // IDs should be unique
118
+ assert!(id1 != id2);
119
+
120
+ state.unregister_runner(id1).await;
121
+ assert_eq!(state.active_runner_count().await, 1);
122
+
123
+ state.unregister_runner(id2).await;
124
+ assert_eq!(state.active_runner_count().await, 0);
125
+ }
126
+
127
+ #[tokio::test]
128
+ async fn test_global_state_virtual_commands() {
129
+ let state = GlobalState::new();
130
+
131
+ // Enabled by default
132
+ assert!(state.are_virtual_commands_enabled());
133
+
134
+ state.disable_virtual_commands();
135
+ assert!(!state.are_virtual_commands_enabled());
136
+
137
+ state.enable_virtual_commands();
138
+ assert!(state.are_virtual_commands_enabled());
139
+ }
140
+
141
+ #[tokio::test]
142
+ async fn test_global_state_signal_handlers() {
143
+ let state = GlobalState::new();
144
+
145
+ // Not installed by default
146
+ assert!(!state.are_signal_handlers_installed());
147
+
148
+ state.set_signal_handlers_installed(true);
149
+ assert!(state.are_signal_handlers_installed());
150
+
151
+ state.set_signal_handlers_installed(false);
152
+ assert!(!state.are_signal_handlers_installed());
153
+ }
154
+
155
+ #[tokio::test]
156
+ async fn test_global_state_reset() {
157
+ let state = GlobalState::new();
158
+
159
+ // Modify state
160
+ state.enable_shell_option("errexit").await;
161
+ state.enable_shell_option("pipefail").await;
162
+ state.register_runner().await;
163
+ state.register_runner().await;
164
+ state.disable_virtual_commands();
165
+
166
+ // Reset
167
+ state.reset().await;
168
+
169
+ // Verify reset
170
+ let settings = state.get_shell_settings().await;
171
+ assert!(!settings.errexit);
172
+ assert!(!settings.pipefail);
173
+ assert_eq!(state.active_runner_count().await, 0);
174
+ assert!(state.are_virtual_commands_enabled());
175
+ }
176
+
177
+ #[tokio::test]
178
+ async fn test_global_state_with_shell_settings() {
179
+ let state = GlobalState::new();
180
+
181
+ state
182
+ .with_shell_settings(|settings| {
183
+ settings.errexit = true;
184
+ settings.verbose = true;
185
+ })
186
+ .await;
187
+
188
+ let settings = state.get_shell_settings().await;
189
+ assert!(settings.errexit);
190
+ assert!(settings.verbose);
191
+ }
192
+
193
+ #[tokio::test]
194
+ async fn test_global_state_initial_cwd() {
195
+ let state = GlobalState::new();
196
+
197
+ let cwd = state.get_initial_cwd().await;
198
+ // Should have an initial cwd
199
+ assert!(cwd.is_some());
200
+ }
201
+
202
+ #[test]
203
+ fn test_global_state_default() {
204
+ let state = GlobalState::default();
205
+ assert!(state.are_virtual_commands_enabled());
206
+ assert!(!state.are_signal_handlers_installed());
207
+ }
@@ -0,0 +1,102 @@
1
+ //! Tests for the streaming module
2
+
3
+ use command_stream::{StreamingRunner, OutputChunk, AsyncIterator};
4
+
5
+ #[tokio::test]
6
+ async fn test_streaming_runner_basic() {
7
+ let runner = StreamingRunner::new("echo hello world");
8
+ let result = runner.collect().await.unwrap();
9
+
10
+ assert!(result.is_success());
11
+ assert!(result.stdout.contains("hello world"));
12
+ }
13
+
14
+ #[tokio::test]
15
+ async fn test_streaming_runner_with_stdin() {
16
+ let runner = StreamingRunner::new("cat")
17
+ .stdin("test input");
18
+ let result = runner.collect().await.unwrap();
19
+
20
+ assert!(result.is_success());
21
+ assert!(result.stdout.contains("test input"));
22
+ }
23
+
24
+ #[tokio::test]
25
+ async fn test_output_stream_chunks() {
26
+ let runner = StreamingRunner::new("echo chunk1 && echo chunk2");
27
+ let mut stream = runner.stream();
28
+
29
+ let mut stdout_chunks = Vec::new();
30
+ let mut exit_code = None;
31
+
32
+ while let Some(chunk) = stream.next().await {
33
+ match chunk {
34
+ OutputChunk::Stdout(data) => {
35
+ stdout_chunks.push(String::from_utf8_lossy(&data).to_string());
36
+ }
37
+ OutputChunk::Stderr(_) => {}
38
+ OutputChunk::Exit(code) => {
39
+ exit_code = Some(code);
40
+ }
41
+ }
42
+ }
43
+
44
+ assert!(exit_code.is_some());
45
+ assert_eq!(exit_code.unwrap(), 0);
46
+ let combined: String = stdout_chunks.join("");
47
+ assert!(combined.contains("chunk1"));
48
+ assert!(combined.contains("chunk2"));
49
+ }
50
+
51
+ #[tokio::test]
52
+ async fn test_streaming_collect_stdout() {
53
+ let runner = StreamingRunner::new("echo stdout only");
54
+ let stream = runner.stream();
55
+
56
+ let stdout = stream.collect_stdout().await;
57
+ let stdout_str = String::from_utf8_lossy(&stdout);
58
+
59
+ assert!(stdout_str.contains("stdout only"));
60
+ }
61
+
62
+ #[tokio::test]
63
+ async fn test_streaming_stderr() {
64
+ // Using sh -c to redirect to stderr
65
+ let runner = StreamingRunner::new("sh -c 'echo error message >&2'");
66
+ let result = runner.collect().await.unwrap();
67
+
68
+ assert!(result.stderr.contains("error message"));
69
+ }
70
+
71
+ #[tokio::test]
72
+ async fn test_streaming_exit_code() {
73
+ let runner = StreamingRunner::new("exit 42");
74
+ let result = runner.collect().await.unwrap();
75
+
76
+ assert_eq!(result.code, 42);
77
+ }
78
+
79
+ #[tokio::test]
80
+ async fn test_streaming_runner_cwd() {
81
+ let runner = StreamingRunner::new("pwd")
82
+ .cwd("/tmp");
83
+ let result = runner.collect().await.unwrap();
84
+
85
+ assert!(result.is_success());
86
+ assert!(result.stdout.contains("/tmp"));
87
+ }
88
+
89
+ #[tokio::test]
90
+ async fn test_streaming_runner_env() {
91
+ use std::collections::HashMap;
92
+
93
+ let mut env = HashMap::new();
94
+ env.insert("TEST_VAR".to_string(), "test_value".to_string());
95
+
96
+ let runner = StreamingRunner::new("sh -c 'echo $TEST_VAR'")
97
+ .env(env);
98
+ let result = runner.collect().await.unwrap();
99
+
100
+ assert!(result.is_success());
101
+ assert!(result.stdout.contains("test_value"));
102
+ }