Repository navigation
Expand file tree
/
Copy pathopen_test.go
More file actions
100 lines (90 loc) · 3.26 KB
/
Copy pathopen_test.go
File metadata and controls
100 lines (90 loc) · 3.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package pdf
import (
"bytes"
"fmt"
"strings"
"testing"
)
// TestOpenMissingFile guards against the regression where os.Open failing
// used to call f.Close() on a nil *os.File, turning a simple "file not
// found" into a nil-pointer panic.
func TestOpenMissingFile(t *testing.T) {
f, r, err := Open("testdata/does-not-exist.pdf")
if err == nil {
t.Fatal("expected error opening missing file, got nil")
}
if f != nil {
t.Fatal("expected nil *os.File on open failure")
}
if r != nil {
t.Fatal("expected nil *Reader on open failure")
}
}
func TestNewReaderRejectsInvalidHeader(t *testing.T) {
data := []byte("this is not a pdf at all")
_, err := NewReader(bytes.NewReader(data), int64(len(data)))
if err == nil || !strings.Contains(err.Error(), "invalid header") {
t.Fatalf("err = %v, want 'invalid header' error", err)
}
}
func TestNewReaderRejectsMissingEOF(t *testing.T) {
// Must be longer than the 100-byte EOF lookback chunk so the tail is
// actually read (NewReader reads the last 100 bytes).
data := []byte("%PDF-1.4\n" + strings.Repeat("x", 200))
_, err := NewReader(bytes.NewReader(data), int64(len(data)))
if err == nil || !strings.Contains(err.Error(), "EOF") {
t.Fatalf("err = %v, want missing %%EOF error", err)
}
}
func TestNewReaderRejectsMissingStartXref(t *testing.T) {
data := []byte("%PDF-1.4\n" + strings.Repeat("x", 200) + "\n%%EOF\n")
_, err := NewReader(bytes.NewReader(data), int64(len(data)))
if err == nil || !strings.Contains(err.Error(), "startxref") {
t.Fatalf("err = %v, want missing startxref error", err)
}
}
// encryptedPDFWithBadPassword builds a minimal single-object PDF whose trailer
// carries a Standard-security /Encrypt dictionary (V=1, R=2, 40-bit) with O and
// U values that do not match the empty password. NewReaderEncrypted must then
// consult the password callback, which returns "" to stop immediately.
func encryptedPDFWithBadPassword() []byte {
// O and U must each be 32 bytes; ID can be any string.
o := strings.Repeat("O", 32)
u := strings.Repeat("U", 32)
id := strings.Repeat("I", 16)
var pdf bytes.Buffer
pdf.WriteString("%PDF-1.4\n")
xrefOffset := pdf.Len()
pdf.WriteString("xref\n0 1\n0000000000 65535 f \n")
fmt.Fprintf(&pdf, "trailer\n<< /Size 1 /ID [(%s)] /Encrypt << /Filter /Standard /V 1 /R 2 /Length 40 /O (%s) /U (%s) /P 0 >> >>\n", id, o, u)
fmt.Fprintf(&pdf, "startxref\n%d\n%%%%EOF\n", xrefOffset)
return pdf.Bytes()
}
func TestNewReaderEncryptedStopsOnEmptyPassword(t *testing.T) {
var calls int
pw := func() string {
calls++
return ""
}
data := encryptedPDFWithBadPassword()
_, err := NewReaderEncrypted(bytes.NewReader(data), int64(len(data)), pw)
if err != ErrInvalidPassword {
t.Fatalf("err = %v, want ErrInvalidPassword", err)
}
if calls != 1 {
t.Fatalf("pw called %d times, want 1 (empty string should stop immediately)", calls)
}
}
func TestEnsureXrefLen(t *testing.T) {
var table []xref
table = ensureXrefLen(table, 3)
if len(table) != 4 || cap(table) < 4 {
t.Fatalf("len/cap = %d/%d, want len 4", len(table), cap(table))
}
table[3] = xref{ptr: objptr{id: 3}}
// Already-large-enough table is returned unchanged.
table2 := ensureXrefLen(table, 1)
if len(table2) != len(table) || table2[3].ptr.id != 3 {
t.Fatal("ensureXrefLen mutated an already-sufficient table")
}
}