This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / patchutil / patchutil_test.go
8.6 kB 406 lines
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} 326 327func TestIsFormatPatch(t *testing.T) { 328 tests := []struct { 329 name string 330 patch string 331 want bool 332 }{ 333 // fast path: sentinel timestamp 334 { 335 name: "sentinel timestamp", 336 patch: "From 3c5035488318164b81f60fe3adcd6c9199d76331 Mon Sep 17 00:00:00 2001\nFrom: Author <a@example.com>\n", 337 want: true, 338 }, 339 // header-count path: various two-header combinations 340 { 341 name: "From and Date headers", 342 patch: "From: Author <a@example.com>\nDate: Mon, 1 Jan 2024 00:00:00 +0000\n", 343 want: true, 344 }, 345 { 346 name: "From and Subject headers", 347 patch: "From: Author <a@example.com>\nSubject: [PATCH] fix thing\n", 348 want: true, 349 }, 350 { 351 name: "Subject and Date headers", 352 patch: "Subject: [PATCH] fix thing\nDate: Mon, 1 Jan 2024 00:00:00 +0000\n", 353 want: true, 354 }, 355 { 356 name: "commit and From headers", 357 patch: "commit abc123\nFrom: Author <a@example.com>\n", 358 want: true, 359 }, 360 // boundary: headers at lines 9 and 10 (0-indexed 8 and 9, last scanned) 361 { 362 name: "headers at lines 9 and 10", 363 patch: "line1\nline2\nline3\nline4\nline5\nline6\nline7\nline8\nFrom: Author <a@example.com>\nSubject: [PATCH] fix\n", 364 want: true, 365 }, 366 // false cases 367 { 368 name: "empty string", 369 patch: "", 370 want: false, 371 }, 372 { 373 name: "single line", 374 patch: "From: Author <a@example.com>", 375 want: false, 376 }, 377 { 378 name: "plain diff", 379 patch: "diff --git a/f.txt b/f.txt\n--- a/f.txt\n+++ b/f.txt\n", 380 want: false, 381 }, 382 { 383 name: "From prefix but wrong timestamp falls through to header count of 1", 384 patch: "From 3c5035488318164b81f60fe3adcd6c9199d76331 Tue Oct 10 12:00:00 2023\nFrom: Author <a@example.com>\n", 385 want: false, 386 }, 387 { 388 name: "only one recognized header", 389 patch: "Subject: [PATCH] fix thing\nsome other line\n", 390 want: false, 391 }, 392 { 393 name: "headers pushed past line 10 are not counted", 394 patch: "line1\nline2\nline3\nline4\nline5\nline6\nline7\nline8\nline9\nline10\nFrom: Author <a@example.com>\nSubject: [PATCH] fix\n", 395 want: false, 396 }, 397 } 398 399 for _, tt := range tests { 400 t.Run(tt.name, func(t *testing.T) { 401 if got := IsFormatPatch(tt.patch); got != tt.want { 402 t.Errorf("IsFormatPatch() = %v, want %v", got, tt.want) 403 } 404 }) 405 } 406}