1package patchutil
2
3import (
4 "errors"
5 "reflect"
6 "testing"
7)
8
9func TestIsPatchValid(t *testing.T) {
10 tests := []struct {
11 name string
12 patch string
13 expected error
14 }{
15 {
16 name: `empty patch`,
17 patch: ``,
18 expected: EmptyPatchError,
19 },
20 {
21 name: `single line patch`,
22 patch: `single line`,
23 expected: EmptyPatchError,
24 },
25 {
26 name: `valid diff patch`,
27 patch: `diff --git a/file.txt b/file.txt
28index abc..def 100644
29--- a/file.txt
30+++ b/file.txt
31@@ -1,3 +1,3 @@
32-old line
33+new line
34 context`,
35 expected: nil,
36 },
37 {
38 name: `valid patch starting with ---`,
39 patch: `--- a/file.txt
40+++ b/file.txt
41@@ -1,3 +1,3 @@
42-old line
43+new line
44 context`,
45 expected: nil,
46 },
47 {
48 name: `valid patch starting with Index`,
49 patch: `Index: file.txt
50==========
51--- a/file.txt
52+++ b/file.txt
53@@ -1,3 +1,3 @@
54-old line
55+new line
56 context`,
57 expected: nil,
58 },
59 {
60 name: `valid patch starting with +++`,
61 patch: `+++ b/file.txt
62--- a/file.txt
63@@ -1,3 +1,3 @@
64-old line
65+new line
66 context`,
67 expected: nil,
68 },
69 {
70 name: `valid patch starting with @@`,
71 patch: `@@ -1,3 +1,3 @@
72-old line
73+new line
74 context
75`,
76 expected: nil,
77 },
78 {
79 name: `valid format patch`,
80 patch: `From 3c5035488318164b81f60fe3adcd6c9199d76331 Mon Sep 17 00:00:00 2001
81From: Author <author@example.com>
82Date: Wed, 16 Apr 2025 11:01:00 +0300
83Subject: [PATCH] Example patch
84
85diff --git a/file.txt b/file.txt
86index 123456..789012 100644
87--- a/file.txt
88+++ b/file.txt
89@@ -1 +1 @@
90-old content
91+new content
92--
932.48.1`,
94 expected: nil,
95 },
96 {
97 name: `invalid format patch`,
98 patch: `From 1234567890123456789012345678901234567890 Mon Sep 17 00:00:00 2001
99From: Author <author@example.com>
100This is not a valid patch format`,
101 expected: FormatPatchError,
102 },
103 {
104 name: `not a patch at all`,
105 patch: `This is
106just some
107random text
108that isn't a patch`,
109 expected: GenericPatchError,
110 },
111 }
112
113 for _, tt := range tests {
114 t.Run(tt.name, func(t *testing.T) {
115 result := IsPatchValid(tt.patch)
116 if !errors.Is(result, tt.expected) {
117 t.Errorf("IsPatchValid() = %v, want %v", result, tt.expected)
118 }
119 })
120 }
121}
122
123func TestSplitPatches(t *testing.T) {
124 tests := []struct {
125 name string
126 input string
127 expected []string
128 }{
129 {
130 name: "Empty input",
131 input: "",
132 expected: []string{},
133 },
134 {
135 name: "No valid patches",
136 input: "This is not a \nJust some random text",
137 expected: []string{},
138 },
139 {
140 name: "Single patch",
141 input: `From 3c5035488318164b81f60fe3adcd6c9199d76331 Mon Sep 17 00:00:00 2001
142From: Author <author@example.com>
143Date: Wed, 16 Apr 2025 11:01:00 +0300
144Subject: [PATCH] Example patch
145
146diff --git a/file.txt b/file.txt
147index 123456..789012 100644
148--- a/file.txt
149+++ b/file.txt
150@@ -1 +1 @@
151-old content
152+new content
153--
1542.48.1`,
155 expected: []string{
156 `From 3c5035488318164b81f60fe3adcd6c9199d76331 Mon Sep 17 00:00:00 2001
157From: Author <author@example.com>
158Date: Wed, 16 Apr 2025 11:01:00 +0300
159Subject: [PATCH] Example patch
160
161diff --git a/file.txt b/file.txt
162index 123456..789012 100644
163--- a/file.txt
164+++ b/file.txt
165@@ -1 +1 @@
166-old content
167+new content
168--
1692.48.1`,
170 },
171 },
172 {
173 name: "Two patches",
174 input: `From 3c5035488318164b81f60fe3adcd6c9199d76331 Mon Sep 17 00:00:00 2001
175From: Author <author@example.com>
176Date: Wed, 16 Apr 2025 11:01:00 +0300
177Subject: [PATCH 1/2] First patch
178
179diff --git a/file1.txt b/file1.txt
180index 123456..789012 100644
181--- a/file1.txt
182+++ b/file1.txt
183@@ -1 +1 @@
184-old content
185+new content
186--
1872.48.1
188From a9529f3b3a653329a5268f0f4067225480207e3c Mon Sep 17 00:00:00 2001
189From: Author <author@example.com>
190Date: Wed, 16 Apr 2025 11:03:11 +0300
191Subject: [PATCH 2/2] Second patch
192
193diff --git a/file2.txt b/file2.txt
194index abcdef..ghijkl 100644
195--- a/file2.txt
196+++ b/file2.txt
197@@ -1 +1 @@
198-foo bar
199+baz qux
200--
2012.48.1`,
202 expected: []string{
203 `From 3c5035488318164b81f60fe3adcd6c9199d76331 Mon Sep 17 00:00:00 2001
204From: Author <author@example.com>
205Date: Wed, 16 Apr 2025 11:01:00 +0300
206Subject: [PATCH 1/2] First patch
207
208diff --git a/file1.txt b/file1.txt
209index 123456..789012 100644
210--- a/file1.txt
211+++ b/file1.txt
212@@ -1 +1 @@
213-old content
214+new content
215--
2162.48.1`,
217 `From a9529f3b3a653329a5268f0f4067225480207e3c Mon Sep 17 00:00:00 2001
218From: Author <author@example.com>
219Date: Wed, 16 Apr 2025 11:03:11 +0300
220Subject: [PATCH 2/2] Second patch
221
222diff --git a/file2.txt b/file2.txt
223index abcdef..ghijkl 100644
224--- a/file2.txt
225+++ b/file2.txt
226@@ -1 +1 @@
227-foo bar
228+baz qux
229--
2302.48.1`,
231 },
232 },
233 {
234 name: "Patches with additional text between them",
235 input: `Some text before the patches
236
237From 3c5035488318164b81f60fe3adcd6c9199d76331 Mon Sep 17 00:00:00 2001
238From: Author <author@example.com>
239Subject: [PATCH] First patch
240
241diff content here
242--
2432.48.1
244
245Some text between patches
246
247From a9529f3b3a653329a5268f0f4067225480207e3c Mon Sep 17 00:00:00 2001
248From: Author <author@example.com>
249Subject: [PATCH] Second patch
250
251more diff content
252--
2532.48.1
254
255Text after patches`,
256 expected: []string{
257 `From 3c5035488318164b81f60fe3adcd6c9199d76331 Mon Sep 17 00:00:00 2001
258From: Author <author@example.com>
259Subject: [PATCH] First patch
260
261diff content here
262--
2632.48.1
264
265Some text between patches`,
266 `From a9529f3b3a653329a5268f0f4067225480207e3c Mon Sep 17 00:00:00 2001
267From: Author <author@example.com>
268Subject: [PATCH] Second patch
269
270more diff content
271--
2722.48.1
273
274Text after patches`,
275 },
276 },
277 {
278 name: "Patches with whitespace padding",
279 input: `
280
281From 3c5035488318164b81f60fe3adcd6c9199d76331 Mon Sep 17 00:00:00 2001
282From: Author <author@example.com>
283Subject: Patch
284
285content
286--
2872.48.1
288
289
290From a9529f3b3a653329a5268f0f4067225480207e3c Mon Sep 17 00:00:00 2001
291From: Author <author@example.com>
292Subject: Another patch
293
294content
295--
2962.48.1
297 `,
298 expected: []string{
299 `From 3c5035488318164b81f60fe3adcd6c9199d76331 Mon Sep 17 00:00:00 2001
300From: Author <author@example.com>
301Subject: Patch
302
303content
304--
3052.48.1`,
306 `From a9529f3b3a653329a5268f0f4067225480207e3c Mon Sep 17 00:00:00 2001
307From: Author <author@example.com>
308Subject: Another patch
309
310content
311--
3122.48.1`,
313 },
314 },
315 }
316
317 for _, tt := range tests {
318 t.Run(tt.name, func(t *testing.T) {
319 result := splitFormatPatch(tt.input)
320 if !reflect.DeepEqual(result, tt.expected) {
321 t.Errorf("splitPatches() = %v, want %v", result, tt.expected)
322 }
323 })
324 }
325}