diff --git a/assets/original/image.pdf b/assets/original/image.pdf new file mode 100644 index 00000000..6d2c2ee9 --- /dev/null +++ b/assets/original/image.pdf @@ -0,0 +1,57 @@ +%PDF-1.7 +1 0 obj +<> +endobj +2 0 obj +<> +endobj +3 0 obj +<>>>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI]>>/MediaBox[0 0 595 842]/Contents 4 0 R>> +endobj +4 0 obj +<> +stream +BT +/F1 12 Tf +50 750 Td +(This is the first line of a multiline string.) Tj +0 -15 Td +(This is the second line of text.) Tj +0 -15 Td +(Below this text will be an inline image.) Tj +ET + +q +50 650 Td +BI + /W 500 + /H 500 + /BPC 8 + /CS /RGB + /F [/DCTDecode] +ID +[BINARY JPEG IMAGE DATA WOULD BE HERE - 500x500 pixels] +EI +Q + +BT +/F1 12 Tf +50 120 Td +(This text appears after the image in the content stream.) Tj +0 -15 Td +(The entire content is a single multiline string in the PDF.) Tj +ET +endstream +endobj +xref +0 5 +0000000000 65535 f +0000000009 00000 n +0000000056 00000 n +0000000107 00000 n +0000000302 00000 n +trailer +<> +startxref +887 +%%EOF diff --git a/assets/original/two_pages.pdf b/assets/original/two_pages.pdf new file mode 100644 index 00000000..26339a54 --- /dev/null +++ b/assets/original/two_pages.pdf @@ -0,0 +1,52 @@ +%PDF-1.4 +%âãÏÓ +1 0 obj +<> +endobj +2 0 obj +<> +endobj +3 0 obj +<>>>/MediaBox[0 0 612 792]/Contents 6 0 R>> +endobj +4 0 obj +<>>>/MediaBox[0 0 612 792]/Contents 7 0 R>> +endobj +5 0 obj +<> +endobj +6 0 obj +<> +stream +BT +/F1 14 Tf +200 400 Td +(Hello from page one!) Tj +ET +endstream +endobj +7 0 obj +<> +stream +BT +/F1 14 Tf +200 400 Td +(Goodbye from page two!) Tj +ET +endstream +endobj +xref +0 8 +0000000000 65535 f +0000000015 00000 n +0000000060 00000 n +0000000111 00000 n +0000000212 00000 n +0000000313 00000 n +0000000374 00000 n +0000000492 00000 n +trailer +<> +startxref +612 +%%EOF diff --git a/assets/original/version1_0.pdf b/assets/original/version1_0.pdf new file mode 100644 index 00000000..7d90281c --- /dev/null +++ b/assets/original/version1_0.pdf @@ -0,0 +1,60 @@ +%PDF-1.0 +%¥±ë % Binary comment for PDF parsers + +1 0 obj +<< /Type /Catalog + /Pages 2 0 R +>> +endobj + +2 0 obj +<< /Type /Pages + /Kids [3 0 R] + /Count 1 +>> +endobj + +3 0 obj +<< /Type /Page + /Parent 2 0 R + /MediaBox [0 0 612 792] + /Contents 4 0 R + /Resources << /ProcSet [/PDF /Text] + /Font << /F1 5 0 R >> + >> +>> +endobj + +4 0 obj +<< /Length 52 >> +stream +BT +/F1 24 Tf +100 700 Td +(PDF 1.0 Example) Tj +ET +endstream +endobj + +5 0 obj +<< /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj + +xref +0 6 +0000000000 65535 f +0000000018 00000 n +0000000072 00000 n +0000000134 00000 n +0000000309 00000 n +0000000411 00000 n +trailer +<< /Size 6 + /Root 1 0 R +>> +startxref +485 +%%EOF diff --git a/assets/original/version1_1.pdf b/assets/original/version1_1.pdf new file mode 100644 index 00000000..25deac7a --- /dev/null +++ b/assets/original/version1_1.pdf @@ -0,0 +1,60 @@ +%PDF-1.1 +%âãÏÓ + +1 0 obj +<< /Type /Catalog + /Pages 2 0 R +>> +endobj + +2 0 obj +<< /Type /Pages + /Kids [3 0 R] + /Count 1 +>> +endobj + +3 0 obj +<< /Type /Page + /Parent 2 0 R + /MediaBox [0 0 612 792] + /Contents 4 0 R + /Resources << /ProcSet [/PDF /Text] + /Font << /F1 5 0 R >> + >> +>> +endobj + +4 0 obj +<< /Length 52 >> +stream +BT +/F1 24 Tf +100 700 Td +(PDF 1.1 Example) Tj +ET +endstream +endobj + +5 0 obj +<< /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj + +xref +0 6 +0000000000 65535 f +0000000018 00000 n +0000000072 00000 n +0000000134 00000 n +0000000309 00000 n +0000000411 00000 n +trailer +<< /Size 6 + /Root 1 0 R +>> +startxref +485 +%%EOF diff --git a/assets/original/version1_2.pdf b/assets/original/version1_2.pdf new file mode 100644 index 00000000..250ef419 --- /dev/null +++ b/assets/original/version1_2.pdf @@ -0,0 +1,43 @@ +%PDF-1.2 +%¥±ë + +1 0 obj +<> +endobj + +2 0 obj +<> +endobj + +3 0 obj +<>>>/MediaBox[0 0 612 792]/Contents 5 0 R>> +endobj + +4 0 obj +<> +endobj + +5 0 obj +<> +stream +BT +/F1 24 Tf +100 700 Td +(hello version 1.2) Tj +ET +endstream +endobj + +xref +0 6 +0000000000 65535 f +0000000018 00000 n +0000000063 00000 n +0000000114 00000 n +0000000223 00000 n +0000000285 00000 n +trailer +<> +startxref +377 +%%EOF diff --git a/assets/original/version1_3.pdf b/assets/original/version1_3.pdf new file mode 100644 index 00000000..0b77084c --- /dev/null +++ b/assets/original/version1_3.pdf @@ -0,0 +1,58 @@ +%PDF-1.3 +1 0 obj +<< /Type /Catalog + /Pages 2 0 R +>> +endobj + +2 0 obj +<< /Type /Pages + /Kids [3 0 R] + /Count 1 +>> +endobj + +3 0 obj +<< /Type /Page + /Parent 2 0 R + /MediaBox [0 0 612 792] + /Contents 4 0 R + /Resources << /ProcSet [/PDF /Text] + /Font << /F1 5 0 R >> + >> +>> +endobj + +4 0 obj +<< /Length 52 >> +stream +BT +/F1 24 Tf +100 700 Td +(PDF 1.3 Example) Tj +ET +endstream +endobj + +5 0 obj +<< /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj + +xref +0 6 +0000000000 65535 f +0000000009 00000 n +0000000063 00000 n +0000000125 00000 n +0000000300 00000 n +0000000402 00000 n +trailer +<< /Size 6 + /Root 1 0 R +>> +startxref +476 +%%EOF diff --git a/assets/original/version1_4.pdf b/assets/original/version1_4.pdf new file mode 100644 index 00000000..81565b2b --- /dev/null +++ b/assets/original/version1_4.pdf @@ -0,0 +1,67 @@ +%PDF-1.4 +1 0 obj +<< /Type /Catalog + /Pages 2 0 R +>> +endobj + +2 0 obj +<< /Type /Pages + /Kids [3 0 R] + /Count 1 +>> +endobj + +3 0 obj +<< /Type /Page + /Parent 2 0 R + /MediaBox [0 0 612 792] + /Contents 4 0 R + /Resources << /ProcSet [/PDF /Text] + /Font << /F1 5 0 R >> + /ExtGState << /GS1 6 0 R >> + >> +>> +endobj + +4 0 obj +<< /Length 78 >> +stream +BT +/F1 24 Tf +100 700 Td +(PDF 1.4 Example with Transparency) Tj +ET +endstream +endobj + +5 0 obj +<< /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj + +6 0 obj +<< /Type /ExtGState + /ca 0.5 + /CA 0.5 +>> +endobj + +xref +0 7 +0000000000 65535 f +0000000009 00000 n +0000000063 00000 n +0000000125 00000 n +0000000342 00000 n +0000000470 00000 n +0000000544 00000 n +trailer +<< /Size 7 + /Root 1 0 R +>> +startxref +603 +%%EOF diff --git a/assets/original/version1_5.pdf b/assets/original/version1_5.pdf new file mode 100644 index 00000000..e09a696f --- /dev/null +++ b/assets/original/version1_5.pdf @@ -0,0 +1,71 @@ +%PDF-1.5 +1 0 obj +<< /Type /Catalog + /Pages 2 0 R + /Version /1.5 +>> +endobj + +2 0 obj +<< /Type /Pages + /Kids [3 0 R] + /Count 1 +>> +endobj + +3 0 obj +<< /Type /Page + /Parent 2 0 R + /MediaBox [0 0 612 792] + /Contents 4 0 R + /Resources << /ProcSet [/PDF /Text] + /Font << /F1 5 0 R >> + >> +>> +endobj + +4 0 obj +<< /Length 52 >> +stream +BT +/F1 24 Tf +100 700 Td +(PDF 1.5 Example) Tj +ET +endstream +endobj + +5 0 obj +<< /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj + +6 0 obj +<< /Type /ObjStm + /N 1 + /First 4 + /Length 19 +>> +stream +7 0 << /Im 8 0 R >> +endstream +endobj + +xref +0 7 +0000000000 65535 f +0000000009 00000 n +0000000075 00000 n +0000000137 00000 n +0000000312 00000 n +0000000414 00000 n +0000000488 00000 n +trailer +<< /Size 7 + /Root 1 0 R +>> +startxref +585 +%%EOF diff --git a/assets/original/version1_6.pdf b/assets/original/version1_6.pdf new file mode 100644 index 00000000..ba33a47d --- /dev/null +++ b/assets/original/version1_6.pdf @@ -0,0 +1,96 @@ +%PDF-1.6 +1 0 obj +<< /Type /Catalog + /Pages 2 0 R + /Version /1.6 +>> +endobj + +2 0 obj +<< /Type /Pages + /Kids [3 0 R] + /Count 1 +>> +endobj + +3 0 obj +<< /Type /Page + /Parent 2 0 R + /MediaBox [0 0 612 792] + /Contents 4 0 R + /Resources << /ProcSet [/PDF /Text] + /Font << /F1 5 0 R >> + >> + /Annots [6 0 R] +>> +endobj + +4 0 obj +<< /Length 52 >> +stream +BT +/F1 24 Tf +100 700 Td +(PDF 1.6 Example) Tj +ET +endstream +endobj + +5 0 obj +<< /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj + +6 0 obj +<< /Type /Annot + /Subtype /3D + /Rect [100 100 400 500] + /3DD 7 0 R + /AP << /N 8 0 R >> +>> +endobj + +7 0 obj +<< /Type /3DStream + /Subtype /U3D + /Length 14 +>> +stream +Placeholder3D +endstream +endobj + +8 0 obj +<< /Type /XObject + /Subtype /Form + /BBox [0 0 300 400] + /Length 25 +>> +stream +q +1 0 0 1 0 0 cm +/Fm1 Do +Q +endstream +endobj + +xref +0 9 +0000000000 65535 f +0000000009 00000 n +0000000075 00000 n +0000000137 00000 n +0000000332 00000 n +0000000434 00000 n +0000000508 00000 n +0000000621 00000 n +0000000708 00000 n +trailer +<< /Size 9 + /Root 1 0 R +>> +startxref +835 +%%EOF diff --git a/assets/original/version1_7.pdf b/assets/original/version1_7.pdf new file mode 100644 index 00000000..68cde71a --- /dev/null +++ b/assets/original/version1_7.pdf @@ -0,0 +1,106 @@ +%PDF-1.7 +1 0 obj +<< /Type /Catalog + /Pages 2 0 R + /Version /1.7 +>> +endobj + +2 0 obj +<< /Type /Pages + /Kids [3 0 R] + /Count 1 +>> +endobj + +3 0 obj +<< /Type /Page + /Parent 2 0 R + /MediaBox [0 0 612 792] + /Contents 4 0 R + /Resources << /ProcSet [/PDF /Text] + /Font << /F1 5 0 R >> + >> + /Annots [6 0 R] +>> +endobj + +4 0 obj +<< /Length 52 >> +stream +BT +/F1 24 Tf +100 700 Td +(PDF 1.7 Example) Tj +ET +endstream +endobj + +5 0 obj +<< /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj + +6 0 obj +<< /Type /Annot + /Subtype /RichMedia + /Rect [100 100 400 500] + /RichMediaContent 7 0 R +>> +endobj + +7 0 obj +<< /Type /RichMediaContent + /Assets 8 0 R + /Configurations [9 0 R] +>> +endobj + +8 0 obj +<< /Names [(asset1) 10 0 R] +>> +endobj + +9 0 obj +<< /Type /RichMediaConfiguration + /Instances [<< /Asset (asset1) >>] +>> +endobj + +10 0 obj +<< /Type /Filespec + /F (media.mp4) + /EF << /F 11 0 R >> +>> +endobj + +11 0 obj +<< /Length 22 >> +stream +PlaceholderMediaContent +endstream +endobj + +xref +0 12 +0000000000 65535 f +0000000009 00000 n +0000000075 00000 n +0000000137 00000 n +0000000332 00000 n +0000000434 00000 n +0000000508 00000 n +0000000612 00000 n +0000000696 00000 n +0000000741 00000 n +0000000826 00000 n +0000000901 00000 n +trailer +<< /Size 12 + /Root 1 0 R +>> +startxref +975 +%%EOF diff --git a/assets/original/version2_0.pdf b/assets/original/version2_0.pdf new file mode 100644 index 00000000..8e6716f7 --- /dev/null +++ b/assets/original/version2_0.pdf @@ -0,0 +1,60 @@ +%PDF-2.0 +%âãÏÓ + +1 0 obj +<< /Type /Catalog + /Pages 2 0 R +>> +endobj + +2 0 obj +<< /Type /Pages + /Kids [3 0 R] + /Count 1 +>> +endobj + +3 0 obj +<< /Type /Page + /Parent 2 0 R + /MediaBox [0 0 612 792] + /Contents 4 0 R + /Resources << /ProcSet [/PDF /Text] + /Font << /F1 5 0 R >> + >> +>> +endobj + +4 0 obj +<< /Length 52 >> +stream +BT +/F1 24 Tf +100 700 Td +(PDF 2.0 Example) Tj +ET +endstream +endobj + +5 0 obj +<< /Type /Font + /Subtype /Type1 + /BaseFont /Helvetica +>> +endobj + +xref +0 6 +0000000000 65535 f +0000000018 00000 n +0000000072 00000 n +0000000134 00000 n +0000000309 00000 n +0000000411 00000 n +trailer +<< /Size 6 + /Root 1 0 R +>> +startxref +485 +%%EOF diff --git a/devbox.json b/devbox.json index 6cc41c40..d3369b8e 100644 --- a/devbox.json +++ b/devbox.json @@ -63,7 +63,9 @@ "docker-client@27.3.1", "gotestsum@latest", "goperf@latest", - "graphviz@latest" + "graphviz@latest", + "psrecord@latest", + "linuxPackages.perf@latest" ], "shell": { "init_hook": [ diff --git a/devbox.lock b/devbox.lock index b9fb3cb3..d26880b1 100644 --- a/devbox.lock +++ b/devbox.lock @@ -645,6 +645,12 @@ } } }, + "linuxPackages.perf@latest": { + "last_modified": "2023-02-24T09:01:09Z", + "resolved": "github:NixOS/nixpkgs/7d0ed7f2e5aea07ab22ccb338d27fbe347ed2f11#linuxPackages.perf", + "source": "devbox-search", + "version": "5.15.95" + }, "nodePackages.jsonlint@1.6.3": { "last_modified": "2024-12-23T21:10:33Z", "resolved": "github:NixOS/nixpkgs/de1864217bfa9b5845f465e771e0ecb48b30e02d#nodePackages.jsonlint", @@ -866,6 +872,70 @@ } } }, + "psrecord@latest": { + "last_modified": "2025-05-16T20:19:48Z", + "resolved": "github:NixOS/nixpkgs/12a55407652e04dcf2309436eb06fef0d3713ef3#psrecord", + "source": "devbox-search", + "version": "1.2", + "systems": { + "aarch64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/g2z5wxy6zm7sf2mbsdjrnaknjxr6hn7r-psrecord-1.2", + "default": true + }, + { + "name": "dist", + "path": "/nix/store/95awalpv6dsxn732vnjzgvmv32s7w2xa-psrecord-1.2-dist" + } + ], + "store_path": "/nix/store/g2z5wxy6zm7sf2mbsdjrnaknjxr6hn7r-psrecord-1.2" + }, + "aarch64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/mr8x3zlxhrp017fs22mxfpqziw4mxs1d-psrecord-1.2", + "default": true + }, + { + "name": "dist", + "path": "/nix/store/w0ql3jy8iawhglz90ivi05m6zz3z0pkh-psrecord-1.2-dist" + } + ], + "store_path": "/nix/store/mr8x3zlxhrp017fs22mxfpqziw4mxs1d-psrecord-1.2" + }, + "x86_64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/apfdsdgls8f9dfx3ah71swjidm68n36i-psrecord-1.2", + "default": true + }, + { + "name": "dist", + "path": "/nix/store/194db77xl7841nsngywyfas21vbsx2d2-psrecord-1.2-dist" + } + ], + "store_path": "/nix/store/apfdsdgls8f9dfx3ah71swjidm68n36i-psrecord-1.2" + }, + "x86_64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/w4k2y4rrqc4fvsdpkjgc1cwzwy9yd8c8-psrecord-1.2", + "default": true + }, + { + "name": "dist", + "path": "/nix/store/pvyvp72mdf8xhn73jf072cbc0cdzrv4r-psrecord-1.2-dist" + } + ], + "store_path": "/nix/store/w4k2y4rrqc4fvsdpkjgc1cwzwy9yd8c8-psrecord-1.2" + } + } + }, "sqlc@1.27.0": { "last_modified": "2024-12-23T21:10:33Z", "resolved": "github:NixOS/nixpkgs/de1864217bfa9b5845f465e771e0ecb48b30e02d#sqlc", diff --git a/internal/document/types/pdf_test.go b/internal/document/types/pdf_test.go index ef042b37..5f5fd132 100644 --- a/internal/document/types/pdf_test.go +++ b/internal/document/types/pdf_test.go @@ -3,6 +3,8 @@ package documenttypes import ( "context" "math" + "os" + "path/filepath" "strings" "testing" @@ -211,60 +213,32 @@ func TestIsCorrupt(t *testing.T) { reason := pdf.IsCorrupt(ctx) assert.Equal(t, InvalidDocumentLargeDimensions, *reason) }) - t.Run("version 1.0", func(t *testing.T) { - pdf := NewPDF(strings.NewReader(PDF1_0)) - reason := pdf.IsCorrupt(ctx) - assert.Nil(t, reason) - }) - t.Run("version 1.1", func(t *testing.T) { - pdf := NewPDF(strings.NewReader(PDF1_1)) + dirPath := "../../../assets/original" + entries, err := os.ReadDir(dirPath) + require.NoError(t, err) - reason := pdf.IsCorrupt(ctx) - assert.Nil(t, reason) - }) - t.Run("version 1.2", func(t *testing.T) { - pdf := NewPDF(strings.NewReader(PDF1_2)) + for _, entry := range entries { + if entry.IsDir() { + continue + } - reason := pdf.IsCorrupt(ctx) - assert.Nil(t, reason) - }) - t.Run("version 1.3", func(t *testing.T) { - pdf := NewPDF(strings.NewReader(PDF1_3)) + fileName := entry.Name() + if strings.ToLower(filepath.Ext(fileName)) != ".pdf" { + continue + } - reason := pdf.IsCorrupt(ctx) - assert.Nil(t, reason) - }) - t.Run("version 1.4", func(t *testing.T) { - pdf := NewPDF(strings.NewReader(PDF1_4)) + t.Run(fileName, func(t *testing.T) { + fullPath := filepath.Join(dirPath, fileName) + file, err := os.Open(fullPath) + require.NoError(t, err) - reason := pdf.IsCorrupt(ctx) - assert.Nil(t, reason) - }) - t.Run("version 1.5", func(t *testing.T) { - pdf := NewPDF(strings.NewReader(PDF1_5)) + pdf := NewPDF(file) - reason := pdf.IsCorrupt(ctx) - assert.Nil(t, reason) - }) - t.Run("version 1.6", func(t *testing.T) { - pdf := NewPDF(strings.NewReader(PDF1_6)) - - reason := pdf.IsCorrupt(ctx) - assert.Nil(t, reason) - }) - t.Run("version 1.7", func(t *testing.T) { - pdf := NewPDF(strings.NewReader(PDF1_7)) - - reason := pdf.IsCorrupt(ctx) - assert.Nil(t, reason) - }) - t.Run("version 2.0", func(t *testing.T) { - pdf := NewPDF(strings.NewReader(PDF2_0)) - - reason := pdf.IsCorrupt(ctx) - assert.Nil(t, reason) - }) + reason := pdf.IsCorrupt(ctx) + assert.Nil(t, reason) + }) + } } func TestNewPDF(t *testing.T) { @@ -283,643 +257,17 @@ func TestNewPDF(t *testing.T) { func TestPDFGetPage(t *testing.T) { ctx := context.Background() t.Run("hello world", func(t *testing.T) { - pdf := NewPDF(strings.NewReader(PDF1_7)) + file, err := os.Open("../../../assets/original/version1_7.pdf") + require.NoError(t, err) + + pdf := NewPDF(file) + pageZero, err := pdf.GetPage(ctx, 0) assert.NoError(t, err) assert.Contains(t, string(pageZero), "PDF 1.7 Example") }) } -const PDF1_0 = `%PDF-1.0 -%¥±ë % Binary comment for PDF parsers - -1 0 obj -<< /Type /Catalog - /Pages 2 0 R ->> -endobj - -2 0 obj -<< /Type /Pages - /Kids [3 0 R] - /Count 1 ->> -endobj - -3 0 obj -<< /Type /Page - /Parent 2 0 R - /MediaBox [0 0 612 792] - /Contents 4 0 R - /Resources << /ProcSet [/PDF /Text] - /Font << /F1 5 0 R >> - >> ->> -endobj - -4 0 obj -<< /Length 52 >> -stream -BT -/F1 24 Tf -100 700 Td -(PDF 1.0 Example) Tj -ET -endstream -endobj - -5 0 obj -<< /Type /Font - /Subtype /Type1 - /BaseFont /Helvetica ->> -endobj - -xref -0 6 -0000000000 65535 f -0000000018 00000 n -0000000072 00000 n -0000000134 00000 n -0000000309 00000 n -0000000411 00000 n -trailer -<< /Size 6 - /Root 1 0 R ->> -startxref -485 -%%EOF` - -const PDF1_1 = `%PDF-1.1 -%âãÏÓ - -1 0 obj -<< /Type /Catalog - /Pages 2 0 R ->> -endobj - -2 0 obj -<< /Type /Pages - /Kids [3 0 R] - /Count 1 ->> -endobj - -3 0 obj -<< /Type /Page - /Parent 2 0 R - /MediaBox [0 0 612 792] - /Contents 4 0 R - /Resources << /ProcSet [/PDF /Text] - /Font << /F1 5 0 R >> - >> ->> -endobj - -4 0 obj -<< /Length 52 >> -stream -BT -/F1 24 Tf -100 700 Td -(PDF 1.1 Example) Tj -ET -endstream -endobj - -5 0 obj -<< /Type /Font - /Subtype /Type1 - /BaseFont /Helvetica ->> -endobj - -xref -0 6 -0000000000 65535 f -0000000018 00000 n -0000000072 00000 n -0000000134 00000 n -0000000309 00000 n -0000000411 00000 n -trailer -<< /Size 6 - /Root 1 0 R ->> -startxref -485 -%%EOF` - -const PDF1_2 = `%PDF-1.2 -%¥±ë - -1 0 obj -<> -endobj - -2 0 obj -<> -endobj - -3 0 obj -<>>>/MediaBox[0 0 612 792]/Contents 5 0 R>> -endobj - -4 0 obj -<> -endobj - -5 0 obj -<> -stream -BT -/F1 24 Tf -100 700 Td -(hello version 1.2) Tj -ET -endstream -endobj - -xref -0 6 -0000000000 65535 f -0000000018 00000 n -0000000063 00000 n -0000000114 00000 n -0000000223 00000 n -0000000285 00000 n -trailer -<> -startxref -377 -%%EOF` - -const PDF1_3 = `%PDF-1.3 -1 0 obj -<< /Type /Catalog - /Pages 2 0 R ->> -endobj - -2 0 obj -<< /Type /Pages - /Kids [3 0 R] - /Count 1 ->> -endobj - -3 0 obj -<< /Type /Page - /Parent 2 0 R - /MediaBox [0 0 612 792] - /Contents 4 0 R - /Resources << /ProcSet [/PDF /Text] - /Font << /F1 5 0 R >> - >> ->> -endobj - -4 0 obj -<< /Length 52 >> -stream -BT -/F1 24 Tf -100 700 Td -(PDF 1.3 Example) Tj -ET -endstream -endobj - -5 0 obj -<< /Type /Font - /Subtype /Type1 - /BaseFont /Helvetica ->> -endobj - -xref -0 6 -0000000000 65535 f -0000000009 00000 n -0000000063 00000 n -0000000125 00000 n -0000000300 00000 n -0000000402 00000 n -trailer -<< /Size 6 - /Root 1 0 R ->> -startxref -476 -%%EOF` - -const PDF1_4 = `%PDF-1.4 -1 0 obj -<< /Type /Catalog - /Pages 2 0 R ->> -endobj - -2 0 obj -<< /Type /Pages - /Kids [3 0 R] - /Count 1 ->> -endobj - -3 0 obj -<< /Type /Page - /Parent 2 0 R - /MediaBox [0 0 612 792] - /Contents 4 0 R - /Resources << /ProcSet [/PDF /Text] - /Font << /F1 5 0 R >> - /ExtGState << /GS1 6 0 R >> - >> ->> -endobj - -4 0 obj -<< /Length 78 >> -stream -BT -/F1 24 Tf -100 700 Td -(PDF 1.4 Example with Transparency) Tj -ET -endstream -endobj - -5 0 obj -<< /Type /Font - /Subtype /Type1 - /BaseFont /Helvetica ->> -endobj - -6 0 obj -<< /Type /ExtGState - /ca 0.5 - /CA 0.5 ->> -endobj - -xref -0 7 -0000000000 65535 f -0000000009 00000 n -0000000063 00000 n -0000000125 00000 n -0000000342 00000 n -0000000470 00000 n -0000000544 00000 n -trailer -<< /Size 7 - /Root 1 0 R ->> -startxref -603 -%%EOF` - -const PDF1_5 = `%PDF-1.5 -1 0 obj -<< /Type /Catalog - /Pages 2 0 R - /Version /1.5 ->> -endobj - -2 0 obj -<< /Type /Pages - /Kids [3 0 R] - /Count 1 ->> -endobj - -3 0 obj -<< /Type /Page - /Parent 2 0 R - /MediaBox [0 0 612 792] - /Contents 4 0 R - /Resources << /ProcSet [/PDF /Text] - /Font << /F1 5 0 R >> - >> ->> -endobj - -4 0 obj -<< /Length 52 >> -stream -BT -/F1 24 Tf -100 700 Td -(PDF 1.5 Example) Tj -ET -endstream -endobj - -5 0 obj -<< /Type /Font - /Subtype /Type1 - /BaseFont /Helvetica ->> -endobj - -6 0 obj -<< /Type /ObjStm - /N 1 - /First 4 - /Length 19 ->> -stream -7 0 << /Im 8 0 R >> -endstream -endobj - -xref -0 7 -0000000000 65535 f -0000000009 00000 n -0000000075 00000 n -0000000137 00000 n -0000000312 00000 n -0000000414 00000 n -0000000488 00000 n -trailer -<< /Size 7 - /Root 1 0 R ->> -startxref -585 -%%EOF` - -const PDF1_6 = `%PDF-1.6 -1 0 obj -<< /Type /Catalog - /Pages 2 0 R - /Version /1.6 ->> -endobj - -2 0 obj -<< /Type /Pages - /Kids [3 0 R] - /Count 1 ->> -endobj - -3 0 obj -<< /Type /Page - /Parent 2 0 R - /MediaBox [0 0 612 792] - /Contents 4 0 R - /Resources << /ProcSet [/PDF /Text] - /Font << /F1 5 0 R >> - >> - /Annots [6 0 R] ->> -endobj - -4 0 obj -<< /Length 52 >> -stream -BT -/F1 24 Tf -100 700 Td -(PDF 1.6 Example) Tj -ET -endstream -endobj - -5 0 obj -<< /Type /Font - /Subtype /Type1 - /BaseFont /Helvetica ->> -endobj - -6 0 obj -<< /Type /Annot - /Subtype /3D - /Rect [100 100 400 500] - /3DD 7 0 R - /AP << /N 8 0 R >> ->> -endobj - -7 0 obj -<< /Type /3DStream - /Subtype /U3D - /Length 14 ->> -stream -Placeholder3D -endstream -endobj - -8 0 obj -<< /Type /XObject - /Subtype /Form - /BBox [0 0 300 400] - /Length 25 ->> -stream -q -1 0 0 1 0 0 cm -/Fm1 Do -Q -endstream -endobj - -xref -0 9 -0000000000 65535 f -0000000009 00000 n -0000000075 00000 n -0000000137 00000 n -0000000332 00000 n -0000000434 00000 n -0000000508 00000 n -0000000621 00000 n -0000000708 00000 n -trailer -<< /Size 9 - /Root 1 0 R ->> -startxref -835 -%%EOF` - -const PDF1_7 = `%PDF-1.7 -1 0 obj -<< /Type /Catalog - /Pages 2 0 R - /Version /1.7 ->> -endobj - -2 0 obj -<< /Type /Pages - /Kids [3 0 R] - /Count 1 ->> -endobj - -3 0 obj -<< /Type /Page - /Parent 2 0 R - /MediaBox [0 0 612 792] - /Contents 4 0 R - /Resources << /ProcSet [/PDF /Text] - /Font << /F1 5 0 R >> - >> - /Annots [6 0 R] ->> -endobj - -4 0 obj -<< /Length 52 >> -stream -BT -/F1 24 Tf -100 700 Td -(PDF 1.7 Example) Tj -ET -endstream -endobj - -5 0 obj -<< /Type /Font - /Subtype /Type1 - /BaseFont /Helvetica ->> -endobj - -6 0 obj -<< /Type /Annot - /Subtype /RichMedia - /Rect [100 100 400 500] - /RichMediaContent 7 0 R ->> -endobj - -7 0 obj -<< /Type /RichMediaContent - /Assets 8 0 R - /Configurations [9 0 R] ->> -endobj - -8 0 obj -<< /Names [(asset1) 10 0 R] ->> -endobj - -9 0 obj -<< /Type /RichMediaConfiguration - /Instances [<< /Asset (asset1) >>] ->> -endobj - -10 0 obj -<< /Type /Filespec - /F (media.mp4) - /EF << /F 11 0 R >> ->> -endobj - -11 0 obj -<< /Length 22 >> -stream -PlaceholderMediaContent -endstream -endobj - -xref -0 12 -0000000000 65535 f -0000000009 00000 n -0000000075 00000 n -0000000137 00000 n -0000000332 00000 n -0000000434 00000 n -0000000508 00000 n -0000000612 00000 n -0000000696 00000 n -0000000741 00000 n -0000000826 00000 n -0000000901 00000 n -trailer -<< /Size 12 - /Root 1 0 R ->> -startxref -975 -%%EOF` - -const PDF2_0 = `%PDF-2.0 -%âãÏÓ - -1 0 obj -<< /Type /Catalog - /Pages 2 0 R ->> -endobj - -2 0 obj -<< /Type /Pages - /Kids [3 0 R] - /Count 1 ->> -endobj - -3 0 obj -<< /Type /Page - /Parent 2 0 R - /MediaBox [0 0 612 792] - /Contents 4 0 R - /Resources << /ProcSet [/PDF /Text] - /Font << /F1 5 0 R >> - >> ->> -endobj - -4 0 obj -<< /Length 52 >> -stream -BT -/F1 24 Tf -100 700 Td -(PDF 2.0 Example) Tj -ET -endstream -endobj - -5 0 obj -<< /Type /Font - /Subtype /Type1 - /BaseFont /Helvetica ->> -endobj - -xref -0 6 -0000000000 65535 f -0000000018 00000 n -0000000072 00000 n -0000000134 00000 n -0000000309 00000 n -0000000411 00000 n -trailer -<< /Size 6 - /Root 1 0 R ->> -startxref -485 -%%EOF` - const pdfTwoPages = `%PDF-1.4 %âãÏÓ 1 0 obj diff --git a/scripts/Taskfile.yml b/scripts/Taskfile.yml index 3ce7a202..8508a21d 100644 --- a/scripts/Taskfile.yml +++ b/scripts/Taskfile.yml @@ -32,6 +32,7 @@ tasks: deps: - task: test:functional - task: lint + graph: psrecord "task fullsuite" --plot out/fullsuite.png --interval 0.1 --include-children precommit: - task: lint deps:tidy: diff --git a/scripts/tests.yml b/scripts/tests.yml index 48ead936..2e9c6f11 100644 --- a/scripts/tests.yml +++ b/scripts/tests.yml @@ -37,17 +37,102 @@ tasks: - rm -rf mocks/* - go tool mockery --log-level="" functional: + - mkdir -p {{.OUT_DIR}} + - task: wait + - | + GOMAXPROCS={{.TEST_PARALLEL}} go test -parallel {{.CPU_COUNT}} \ + -coverpkg={{.INTERNAL}},{{.API}},{{.PKG}} \ + -coverprofile={{.COVERAGE_FILE}} \ + ./... + - task: coverage + race: GOMAXPROCS={{.TEST_PARALLEL}} go test -parallel {{.CPU_COUNT}} -race ./... + graph: psrecord "task test:functional" --plot out/test.png --interval 0.1 --include-children + wait: docker wait $(docker ps -q --filter "label=org.testcontainers.ryuk=true") 2>/dev/null || true + mem: + vars: + NUM_RESULTS: 5 + RESULTS_FILE: "{{ .OUT_DIR }}/mem.out" cmds: - - mkdir -p {{.OUT_DIR}} - | - GOMAXPROCS={{.TEST_PARALLEL}} go test -parallel {{.CPU_COUNT}} \ - -coverpkg={{.INTERNAL}},{{.API}},{{.PKG}} \ - -coverprofile={{.COVERAGE_FILE}} \ - ./... - - task: coverage - race: - cmds: - - GOMAXPROCS={{.TEST_PARALLEL}} go test -parallel {{.CPU_COUNT}} -race ./... + YELLOW='\033[0;33m' + BLUE='\033[0;34m' + NC='\033[0m' # No Color + + get_memory_usage() { + local profile_file=$1 + if [ ! -f "$profile_file" ] || [ ! -s "$profile_file" ]; then + return + fi + + local mem_mb=$(go tool pprof -top "{{ .RESULTS_FILE }}" 2>/dev/null | \ + grep -E "^\s*[0-9]" | head -1 | \ + awk '{print $1}' | \ + sed 's/MB//g' | sed 's/KB//g' | sed 's/GB//g' | \ + sed 's/[^0-9.]//g') + + if go tool pprof -top "{{ .RESULTS_FILE }}" 2>/dev/null | head -1 | grep -q "KB"; then + mem_mb=$(echo "$mem_mb / 1024" | bc -l 2>/dev/null || echo "0") + fi + + if go tool pprof -top "{{ .RESULTS_FILE }}" 2>/dev/null | head -1 | grep -q "GB"; then + mem_mb=$(echo "$mem_mb * 1024" | bc -l 2>/dev/null || echo "0") + fi + + echo "${mem_mb:-0}" + } + + test_package() { + local pkg=$1 + local pkg_short=$(basename "$pkg") + local profile="{{ .OUT_DIR }}/mem_${pkg_short}_$(date +%s).prof" + + echo -e "${YELLOW}Testing:${NC} $pkg ... " + + # Run test with memory profiling (with timeout) + if timeout 120 go test -memprofile="$profile" "$pkg" >/dev/null 2>&1; then + local mem_usage=$(get_memory_usage "$profile") + echo -e "✅ ${mem_usage} MB" + echo "$mem_usage|$pkg" >> "{{ .RESULTS_FILE }}" + else + echo -e "❌ FAILED/TIMEOUT" + echo "0|$pkg" >> "{{ .RESULTS_FILE }}" + fi + } + + echo -e "${BLUE}Go Test Memory Usage Analysis${NC}" + echo -e "${BLUE}==============================${NC}" + echo "Profile directory: out/" + echo "" + echo "Running tests with memory profiling..." + echo "" + + for pkg in $(go list ./... 2>/dev/null || echo "."); do + task test:wait + test_package "$pkg" + done + + if [ ! -f "{{ .RESULTS_FILE }}" ] || [ ! -s "{{ .RESULTS_FILE }}" ]; then + exit 1 + fi + + echo "" + echo -e "${BLUE}Memory Usage Rankings:${NC}" + echo -e "${BLUE}=====================${NC}" + + { + echo "MEMORY(MB)|PACKAGE" + echo "----------|--------" + sort -t'|' -k1 -nr "{{ .RESULTS_FILE }}" | head -{{ .NUM_RESULTS }} + } | column -t -s'|' + + echo "" + echo -e "${BLUE}Summary:${NC}" + + total_mem=$(awk -F'|' '{sum+=$1} END {printf "%.2f", sum}' "{{ .RESULTS_FILE }}") + total_packages=$(wc -l < "{{ .RESULTS_FILE }}") + + echo "Total packages tested: $total_packages" + echo "Total memory usage: ${total_mem} MB" perf: vars: NUM_RESULTS: 5