package fileops import ( "testing" ) func TestDeleteLinesInFile(t *testing.T) { tests := []struct { name string content string pattern string dryRun bool wantDeleted []int wantContent string }{ { name: "delete single matching line", content: "keep this\ndelete foo\nkeep this too\n", pattern: "foo", wantDeleted: []int{2}, wantContent: "keep this\nkeep this too\n", }, { name: "delete multiple matching lines", content: "foo line\nkeep\nanother foo\n", pattern: "foo", wantDeleted: []int{1, 3}, wantContent: "keep\n", }, { name: "delete all lines", content: "foo\nfoo\nfoo\n", pattern: "foo", wantDeleted: []int{1, 2, 3}, wantContent: "", }, { name: "no match leaves file unchanged", content: "line one\nline two\n", pattern: "xyz", wantDeleted: nil, wantContent: "line one\nline two\n", }, { name: "dry run reports deletions but does not write", content: "foo bar\nkeep\n", pattern: "foo", dryRun: true, wantDeleted: []int{1}, wantContent: "foo bar\nkeep\n", }, { name: "pattern matches substring of line", content: "prefix_foo_suffix\nclean\n", pattern: "foo", wantDeleted: []int{1}, wantContent: "clean\n", }, { name: "empty file", content: "", pattern: "foo", wantDeleted: nil, wantContent: "", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { path := writeTempFile(t, tt.content) res, err := DeleteLinesInFile(path, tt.pattern, tt.dryRun) if err != nil { t.Fatalf("unexpected error: %v", err) } if !equalIntSlice(res.DeletedLines, tt.wantDeleted) { t.Errorf("DeletedLines = %v, want %v", res.DeletedLines, tt.wantDeleted) } got := readTempFile(t, path) if got != tt.wantContent { t.Errorf("file content = %q, want %q", got, tt.wantContent) } }) } } func TestDeleteLinesInFile_MissingFile(t *testing.T) { _, err := DeleteLinesInFile("/no/such/file.txt", "foo", false) if err == nil { t.Error("expected error for missing file, got nil") } } func TestDeleteLinesInFileRegex(t *testing.T) { tests := []struct { name string content string pattern string dryRun bool wantDeleted []int wantContent string wantErr bool }{ { name: "delete lines matching regex", content: "error: bad thing\ninfo: ok\nerror: another\n", pattern: `^error:`, wantDeleted: []int{1, 3}, wantContent: "info: ok\n", }, { name: "digit pattern", content: "line 1\nno digits\nline 2\n", pattern: `\d`, wantDeleted: []int{1, 3}, wantContent: "no digits\n", }, { name: "no match", content: "hello\nworld\n", pattern: `\d+`, wantDeleted: nil, wantContent: "hello\nworld\n", }, { name: "invalid regex returns error", content: "foo\n", pattern: `[bad`, wantErr: true, }, { name: "dry run with regex", content: "debug log\ninfo log\n", pattern: `^debug`, dryRun: true, wantDeleted: []int{1}, wantContent: "debug log\ninfo log\n", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { path := writeTempFile(t, tt.content) res, err := DeleteLinesInFileRegex(path, tt.pattern, tt.dryRun) if tt.wantErr { if err == nil { t.Error("expected error, got nil") } return } if err != nil { t.Fatalf("unexpected error: %v", err) } if !equalIntSlice(res.DeletedLines, tt.wantDeleted) { t.Errorf("DeletedLines = %v, want %v", res.DeletedLines, tt.wantDeleted) } got := readTempFile(t, path) if got != tt.wantContent { t.Errorf("file content = %q, want %q", got, tt.wantContent) } }) } }