Skip to content

Commit 7c22b73

Browse files
Ming0213Copilotgenedna
authored
为add、diff、remove命令补充测试用例#1257 (#1292)
* feat:增加add、diff、remove命令测试用例 Signed-off-by: WangHaiMing <[email protected]> * Update libra/tests/command/remove_test.rs Co-authored-by: Copilot <[email protected]> Signed-off-by: Ming0213 <[email protected]> * Update libra/tests/command/add_test.rs Co-authored-by: Copilot <[email protected]> Signed-off-by: Ming0213 <[email protected]> * Update libra/tests/command/add_test.rs Co-authored-by: Copilot <[email protected]> Signed-off-by: Ming0213 <[email protected]> * Update libra/tests/command/diff_test.rs Co-authored-by: Copilot <[email protected]> Signed-off-by: Ming0213 <[email protected]> * bugFix:修复add_test.rs、diff_test.rs、remove_test.rs三个测试用例的Clippy检查的报错 Signed-off-by: WangHaiMing <[email protected]> * libra:为add、diff、remove命令添加测试用例 Signed-off-by: WangHaiMing <[email protected]> * Update libra/tests/command/add_test.rs Co-authored-by: Copilot <[email protected]> Signed-off-by: Ming0213 <[email protected]> * Update libra/tests/command/add_test.rs Co-authored-by: Copilot <[email protected]> Signed-off-by: Ming0213 <[email protected]> * Update libra/tests/command/add_test.rs Co-authored-by: Copilot <[email protected]> Signed-off-by: Ming0213 <[email protected]> * bugFix:修复add_test、remove_test、diff_test三个文件的相应ClipyCheck错误 Signed-off-by: WangHaiMing <[email protected]> * bugFix:修复ClipyCheck错误 Signed-off-by: WangHaiMing <[email protected]> * bugFix:继续修复ClipyCheck错误 Signed-off-by: WangHaiMing <[email protected]> * bugFix:继续修复ClipyCheck错误 Signed-off-by: WangHaiMing <[email protected]> * bugFix:继续修复ClipyCheck错误 Signed-off-by: WangHaiMing <[email protected]> * bugFix:继续修复ClipuCheck错误 Signed-off-by: WangHaiMing <[email protected]> * bugFix:继续修复ClippyCheck错误 Signed-off-by: WangHaiMing <[email protected]> * bugFix:修复报错 Signed-off-by: WangHaiMing <[email protected]> * Update libra/tests/command/remove_test.rs Co-authored-by: Copilot <[email protected]> Signed-off-by: Ming0213 <[email protected]> * Update libra/tests/command/remove_test.rs Co-authored-by: Copilot <[email protected]> Signed-off-by: Ming0213 <[email protected]> * bugFix:修复错误 Signed-off-by: WangHaiMing <[email protected]> * bugFix:修复错误 Signed-off-by: WangHaiMing <[email protected]> * bugFix:修复错误 Signed-off-by: WangHaiMing <[email protected]> --------- Signed-off-by: WangHaiMing <[email protected]> Signed-off-by: Ming0213 <[email protected]> Co-authored-by: Copilot <[email protected]> Co-authored-by: Quanyi Ma <[email protected]>
1 parent b5a7558 commit 7c22b73

File tree

6 files changed

+878
-253
lines changed

6 files changed

+878
-253
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ Cargo.lock
2121
.DS_Store
2222
**/*.dylib
2323

24+
.cursor
25+
.md
26+
2427
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2528
.VSCodeCounter
2629

libra/src/command/remove.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,15 @@ pub fn execute(args: RemoveArgs) -> Result<(), GitError> {
3333
let mut index = Index::load(&idx_file)?;
3434

3535
// check if pathspec is all in index (skip if force is enabled)
36-
if !args.force && !validate_pathspec(&args.pathspec, &index) {
37-
return Ok(());
36+
if !args.force {
37+
validate_pathspec(&args.pathspec, &index)?
3838
}
3939

4040
let dirs = get_dirs(&args.pathspec, &index, args.force);
4141
if !dirs.is_empty() && !args.recursive {
42-
println!(
43-
"fatal: not removing '{}' recursively without -r",
44-
dirs[0].bright_blue()
45-
); // Git print first
46-
return Ok(());
42+
let error_msg = format!("not removing '{}' recursively without -r", dirs[0]);
43+
println!("fatal: {error_msg}");
44+
return Err(GitError::CustomError(error_msg));
4745
}
4846

4947
for path_str in args.pathspec.iter() {
@@ -87,10 +85,11 @@ pub fn execute(args: RemoveArgs) -> Result<(), GitError> {
8785

8886
/// check if pathspec is all valid(in index)
8987
/// - if path is a dir, check if any file in the dir is in index
90-
fn validate_pathspec(pathspec: &[String], index: &Index) -> bool {
88+
fn validate_pathspec(pathspec: &[String], index: &Index) -> Result<(), GitError> {
9189
if pathspec.is_empty() {
92-
println!("fatal: No pathspec was given. Which files should I remove?");
93-
return false;
90+
let error_msg = "No pathspec was given. Which files should I remove?".to_string();
91+
println!("fatal: {error_msg}");
92+
return Err(GitError::CustomError(error_msg));
9493
}
9594
for path_str in pathspec.iter() {
9695
let path = PathBuf::from(path_str);
@@ -99,12 +98,13 @@ fn validate_pathspec(pathspec: &[String], index: &Index) -> bool {
9998
// not tracked, but path may be a directory
10099
// check if any tracked file in the directory
101100
if !index.contains_dir_file(&path_wd) {
102-
println!("fatal: pathspec '{path_str}' did not match any files");
103-
return false;
101+
let error_msg = format!("pathspec '{path_str}' did not match any files");
102+
println!("fatal: {error_msg}");
103+
return Err(GitError::CustomError(error_msg));
104104
}
105105
}
106106
}
107-
true
107+
Ok(())
108108
}
109109

110110
/// run after `validate_pathspec`

libra/tests/command/add_test.rs

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,254 @@
1+
use super::*;
2+
use std::fs;
3+
use std::io::Write;
14

5+
#[tokio::test]
6+
#[serial]
7+
/// Tests the basic functionality of add command by adding a single file
8+
async fn test_add_single_file() {
9+
let test_dir = tempdir().unwrap();
10+
test::setup_with_new_libra_in(test_dir.path()).await;
11+
let _guard = test::ChangeDirGuard::new(test_dir.path());
12+
13+
// Create a new file
14+
let file_content = "Hello, World!";
15+
let file_path = "test_file.txt";
16+
let mut file = fs::File::create(file_path).unwrap();
17+
file.write_all(file_content.as_bytes()).unwrap();
18+
19+
// Execute add command
20+
add::execute(AddArgs {
21+
pathspec: vec![String::from(file_path)],
22+
all: false,
23+
update: false,
24+
refresh: false,
25+
verbose: false,
26+
dry_run: false,
27+
ignore_errors: false,
28+
})
29+
.await;
30+
31+
// Verify the file was added to index.
32+
let changes = changes_to_be_committed().await;
33+
34+
assert!(changes.new.iter().any(|x| x.to_str().unwrap() == file_path));
35+
}
36+
37+
#[tokio::test]
38+
#[serial]
39+
/// Tests adding multiple files at once
40+
async fn test_add_multiple_files() {
41+
let test_dir = tempdir().unwrap();
42+
test::setup_with_new_libra_in(test_dir.path()).await;
43+
let _guard = test::ChangeDirGuard::new(test_dir.path());
44+
45+
// Create multiple files
46+
for i in 1..=3 {
47+
let file_content = format!("File content {i}");
48+
let file_path = format!("test_file_{i}.txt");
49+
let mut file = fs::File::create(&file_path).unwrap();
50+
file.write_all(file_content.as_bytes()).unwrap();
51+
}
52+
53+
// Execute add command
54+
add::execute(AddArgs {
55+
pathspec: vec![
56+
String::from("test_file_1.txt"),
57+
String::from("test_file_2.txt"),
58+
String::from("test_file_3.txt"),
59+
],
60+
all: false,
61+
update: false,
62+
refresh: false,
63+
verbose: false,
64+
dry_run: false,
65+
ignore_errors: false,
66+
})
67+
.await;
68+
69+
// Verify all files were added to index
70+
let changes = changes_to_be_committed().await;
71+
assert!(changes.new.iter().any(|x| x.to_str().unwrap() == "test_file_1.txt"));
72+
assert!(changes.new.iter().any(|x| x.to_str().unwrap() == "test_file_2.txt"));
73+
assert!(changes.new.iter().any(|x| x.to_str().unwrap() == "test_file_3.txt"));
74+
}
75+
76+
#[tokio::test]
77+
#[serial]
78+
/// Tests the --all flag which adds all files in the working tree
79+
async fn test_add_all_flag() {
80+
let test_dir = tempdir().unwrap();
81+
test::setup_with_new_libra_in(test_dir.path()).await;
82+
let _guard = test::ChangeDirGuard::new(test_dir.path());
83+
84+
// Create multiple files
85+
for i in 1..=3 {
86+
let file_content = format!("File content {i}");
87+
let file_path = format!("test_file_{i}.txt");
88+
let mut file = fs::File::create(&file_path).unwrap();
89+
file.write_all(file_content.as_bytes()).unwrap();
90+
}
91+
92+
// Execute add command with --all flag
93+
add::execute(AddArgs {
94+
pathspec: vec![],
95+
all: true,
96+
update: false,
97+
refresh: false,
98+
verbose: false,
99+
dry_run: false,
100+
ignore_errors: false,
101+
})
102+
.await;
103+
104+
// Verify all files were added to index
105+
let changes = changes_to_be_committed().await;
106+
assert!(changes.new.iter().any(|x| x.to_str().unwrap() == "test_file_1.txt"));
107+
assert!(changes.new.iter().any(|x| x.to_str().unwrap() == "test_file_2.txt"));
108+
assert!(changes.new.iter().any(|x| x.to_str().unwrap() == "test_file_3.txt"));
109+
}
110+
111+
#[tokio::test]
112+
#[serial]
113+
/// Tests the --update flag which only updates files already in the index
114+
async fn test_add_update_flag() {
115+
let test_dir = tempdir().unwrap();
116+
test::setup_with_new_libra_in(test_dir.path()).await;
117+
let _guard = test::ChangeDirGuard::new(test_dir.path());
118+
119+
// Create files and add one to the index
120+
let tracked_file = "tracked_file.txt";
121+
let untracked_file = "untracked_file.txt";
122+
123+
// Create and write initial content
124+
let mut file1 = fs::File::create(tracked_file).unwrap();
125+
file1.write_all(b"Initial content").unwrap();
126+
127+
let mut file2 = fs::File::create(untracked_file).unwrap();
128+
file2.write_all(b"Initial content").unwrap();
129+
130+
// Add only one file to the index
131+
add::execute(AddArgs {
132+
pathspec: vec![String::from(tracked_file)],
133+
all: false,
134+
update: false,
135+
refresh: false,
136+
verbose: false,
137+
dry_run: false,
138+
ignore_errors: false,
139+
})
140+
.await;
141+
142+
// Modify both files
143+
let mut file1 = fs::OpenOptions::new().write(true).truncate(true).open(tracked_file).unwrap();
144+
file1.write_all(b" - Modified").unwrap();
145+
146+
let mut file2 = fs::OpenOptions::new().write(true).truncate(true).open(untracked_file).unwrap();
147+
file2.write_all(b" - Modified").unwrap();
148+
149+
// Execute add command with --update flag
150+
add::execute(AddArgs {
151+
pathspec: vec![String::from(".")],
152+
all: false,
153+
update: true,
154+
refresh: false,
155+
verbose: false,
156+
dry_run: false,
157+
ignore_errors: false,
158+
})
159+
.await;
160+
161+
// Verify only tracked file was updated
162+
let changes = changes_to_be_staged();
163+
// Tracked file should not appear in changes (because it was updated in index)
164+
assert!(!changes.modified.iter().any(|x| x.to_str().unwrap() == tracked_file));
165+
// Untracked file should still be untracked and show as new
166+
assert!(changes.new.iter().any(|x| x.to_str().unwrap() == untracked_file));
167+
}
168+
169+
#[tokio::test]
170+
#[serial]
171+
/// Tests adding files with respect to ignore patterns in .libraignore
172+
async fn test_add_with_ignore_patterns() {
173+
let test_dir = tempdir().unwrap();
174+
test::setup_with_new_libra_in(test_dir.path()).await;
175+
let _guard = test::ChangeDirGuard::new(test_dir.path());
176+
177+
// Create .libraignore file
178+
let mut ignore_file = fs::File::create(".libraignore").unwrap();
179+
ignore_file.write_all(b"ignored_*.txt\nignore_dir/**").unwrap();
180+
181+
// Create files that should be ignored and not ignored
182+
let ignored_file = "ignored_file.txt";
183+
let tracked_file = "tracked_file.txt";
184+
185+
// Create directory that should be ignored
186+
fs::create_dir("ignore_dir").unwrap();
187+
let ignored_dir_file = "ignore_dir/file.txt";
188+
189+
// Create and write content
190+
let mut file1 = fs::File::create(ignored_file).unwrap();
191+
file1.write_all(b"Should be ignored").unwrap();
192+
193+
let mut file2 = fs::File::create(tracked_file).unwrap();
194+
file2.write_all(b"Should be tracked").unwrap();
195+
196+
let mut file3 = fs::File::create(ignored_dir_file).unwrap();
197+
file3.write_all(b"Should be ignored").unwrap();
198+
199+
// Execute add command with all files
200+
add::execute(AddArgs {
201+
pathspec: vec![String::from(".")],
202+
all: true,
203+
update: false,
204+
refresh: false,
205+
verbose: false,
206+
dry_run: false,
207+
ignore_errors: false,
208+
})
209+
.await;
210+
211+
// Verify only non-ignored files were added
212+
let changes_staged = changes_to_be_staged();
213+
let changes_committed = changes_to_be_committed().await;
214+
215+
// Ignored files should not appear in any status (they are ignored)
216+
assert!(!changes_staged.new.iter().any(|x| x.to_str().unwrap() == ignored_file));
217+
assert!(!changes_staged.new.iter().any(|x| x.to_str().unwrap() == ignored_dir_file));
218+
assert!(!changes_committed.new.iter().any(|x| x.to_str().unwrap() == ignored_file));
219+
assert!(!changes_committed.new.iter().any(|x| x.to_str().unwrap() == ignored_dir_file));
220+
221+
// Non-ignored file should not show as new in staged (was added) but should show in committed
222+
assert!(!changes_staged.new.iter().any(|x| x.to_str().unwrap() == tracked_file));
223+
assert!(changes_committed.new.iter().any(|x| x.to_str().unwrap() == tracked_file));
224+
}
225+
226+
#[tokio::test]
227+
#[serial]
228+
/// Tests the dry-run flag which should not actually add files
229+
async fn test_add_dry_run() {
230+
let test_dir = tempdir().unwrap();
231+
test::setup_with_new_libra_in(test_dir.path()).await;
232+
let _guard = test::ChangeDirGuard::new(test_dir.path());
233+
234+
// Create a file.
235+
let file_path = "test_file.txt";
236+
let mut file = fs::File::create(file_path).unwrap();
237+
file.write_all(b"Test content").unwrap();
238+
239+
// Execute add command with dry-run
240+
add::execute(AddArgs {
241+
pathspec: vec![String::from(file_path)],
242+
all: false,
243+
update: false,
244+
refresh: false,
245+
verbose: false,
246+
dry_run: true,
247+
ignore_errors: false,
248+
})
249+
.await;
250+
251+
// Verify the file was not actually added to index
252+
let changes = changes_to_be_staged();
253+
assert!(changes.new.iter().any(|x| x.to_str().unwrap() == file_path));
254+
}

0 commit comments

Comments
 (0)