package lib import ( "archive/zip" "bytes" "image" "image/color" "image/png" "testing" ) // TestWatermarkPDF tests PDF watermarking with a minimal PDF. func TestWatermarkPDF(t *testing.T) { // Minimal valid PDF (empty page) minimalPDF := []byte(`%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] >> endobj xref 0 4 0000000000 65535 f 0000000009 00000 n 0000000058 00000 n 0000000115 00000 n trailer << /Size 4 /Root 1 0 R >> startxref 192 %%EOF`) label := "CONFIDENTIAL - Test User - 2026-02-28 - TestProject" out, err := WatermarkPDF(minimalPDF, label) if err != nil { t.Fatalf("WatermarkPDF failed: %v", err) } // Basic checks if len(out) == 0 { t.Fatal("WatermarkPDF returned empty output") } // Watermarked PDF should be larger than original if len(out) <= len(minimalPDF) { t.Errorf("Watermarked PDF (%d bytes) should be larger than original (%d bytes)", len(out), len(minimalPDF)) } // Should still start with PDF header if !bytes.HasPrefix(out, []byte("%PDF")) { t.Error("Output doesn't look like a PDF (missing %PDF header)") } } // TestWatermarkImagePNG tests image watermarking with PNG. func TestWatermarkImagePNG(t *testing.T) { // Create a minimal test PNG (100x100 red square) img := image.NewRGBA(image.Rect(0, 0, 100, 100)) red := color.RGBA{255, 0, 0, 255} for y := 0; y < 100; y++ { for x := 0; x < 100; x++ { img.Set(x, y, red) } } var buf bytes.Buffer if err := png.Encode(&buf, img); err != nil { t.Fatalf("Failed to create test PNG: %v", err) } originalPNG := buf.Bytes() label := "CONFIDENTIAL - Test User - 2026-02-28" out, err := WatermarkImage(originalPNG, "image/png", label) if err != nil { t.Fatalf("WatermarkImage failed: %v", err) } // Basic checks if len(out) == 0 { t.Fatal("WatermarkImage returned empty output") } // Verify it's still a valid PNG _, err = png.Decode(bytes.NewReader(out)) if err != nil { t.Errorf("Output is not a valid PNG: %v", err) } } // TestWatermarkDOCX tests DOCX watermarking with a minimal document. func TestWatermarkDOCX(t *testing.T) { // Create a minimal DOCX (which is a ZIP file with specific structure) minimalDOCX := createMinimalDOCX() label := "CONFIDENTIAL - Test User - 2026-02-28 - TestProject" out, err := WatermarkDOCX(minimalDOCX, label) if err != nil { t.Fatalf("WatermarkDOCX failed: %v", err) } // Basic checks if len(out) == 0 { t.Fatal("WatermarkDOCX returned empty output") } // Watermarked DOCX should be larger (we added header) if len(out) <= len(minimalDOCX) { t.Errorf("Watermarked DOCX (%d bytes) should be larger than original (%d bytes)", len(out), len(minimalDOCX)) } // Should still be a valid ZIP if !bytes.HasPrefix(out, []byte("PK")) { t.Error("Output doesn't look like a DOCX/ZIP (missing PK header)") } } // TestWatermarkDispatch tests the main dispatch function. func TestWatermarkDispatch(t *testing.T) { tests := []struct { name string mimeType string data []byte }{ {"unknown type passthrough", "application/octet-stream", []byte("hello world")}, {"text passthrough", "text/plain", []byte("hello world")}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { out, err := Watermark(tt.data, tt.mimeType, "test label") if err != nil { t.Errorf("Watermark failed: %v", err) } // Unknown types should pass through unchanged if !bytes.Equal(out, tt.data) { t.Error("Unknown MIME type should pass through unchanged") } }) } } // TestWatermarkEmptyInput tests error handling for empty inputs. func TestWatermarkEmptyInput(t *testing.T) { _, err := WatermarkPDF(nil, "test") if err == nil { t.Error("WatermarkPDF should fail on nil input") } _, err = WatermarkImage(nil, "image/png", "test") if err == nil { t.Error("WatermarkImage should fail on nil input") } _, err = WatermarkDOCX(nil, "test") if err == nil { t.Error("WatermarkDOCX should fail on nil input") } } // createMinimalDOCX creates a minimal valid DOCX for testing. func createMinimalDOCX() []byte { var buf bytes.Buffer w := zip.NewWriter(&buf) // [Content_Types].xml contentTypes := ` ` f, _ := w.Create("[Content_Types].xml") f.Write([]byte(contentTypes)) // _rels/.rels rels := ` ` f, _ = w.Create("_rels/.rels") f.Write([]byte(rels)) // word/document.xml doc := ` Test Document ` f, _ = w.Create("word/document.xml") f.Write([]byte(doc)) // word/_rels/document.xml.rels docRels := ` ` f, _ = w.Create("word/_rels/document.xml.rels") f.Write([]byte(docRels)) w.Close() return buf.Bytes() }