github.com/pdfcpu/pdfcpu@v0.11.1/pkg/api/test/api_test.go (about) 1 /* 2 Copyright 2018 The pdf Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package test 18 19 import ( 20 "fmt" 21 "io" 22 "os" 23 "path/filepath" 24 "sort" 25 "strings" 26 "testing" 27 "time" 28 29 "github.com/pdfcpu/pdfcpu/pkg/api" 30 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu" 31 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/model" 32 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/types" 33 ) 34 35 var inDir, outDir, resDir, samplesDir string 36 var conf *model.Configuration 37 38 func isTrueType(filename string) bool { 39 s := strings.ToLower(filename) 40 return strings.HasSuffix(s, ".ttf") || strings.HasSuffix(s, ".ttc") 41 } 42 43 func userFonts(dir string) ([]string, error) { 44 files, err := os.ReadDir(dir) 45 if err != nil { 46 return nil, err 47 } 48 ff := []string(nil) 49 for _, f := range files { 50 if isTrueType(f.Name()) { 51 fn := filepath.Join(dir, f.Name()) 52 ff = append(ff, fn) 53 } 54 } 55 return ff, nil 56 } 57 58 func TestMain(m *testing.M) { 59 inDir = filepath.Join("..", "..", "testdata") 60 resDir = filepath.Join(inDir, "resources") 61 samplesDir = filepath.Join("..", "..", "samples") 62 63 conf = api.LoadConfiguration() 64 if os.Getenv("GITHUB_ACTIONS") == "true" { 65 conf.Offline = true 66 } 67 fmt.Printf("conf.Offline: %t\n", conf.Offline) 68 69 // Install test user fonts from pkg/testdata/fonts. 70 fonts, err := userFonts(filepath.Join(inDir, "fonts")) 71 if err != nil { 72 fmt.Printf("%v", err) 73 os.Exit(1) 74 } 75 76 if err := api.InstallFonts(fonts); err != nil { 77 fmt.Printf("%v", err) 78 os.Exit(1) 79 } 80 81 if outDir, err = os.MkdirTemp("", "pdfcpu_api_tests"); err != nil { 82 fmt.Printf("%v", err) 83 os.Exit(1) 84 } 85 // fmt.Printf("outDir = %s\n", outDir) 86 87 exitCode := m.Run() 88 89 if err = os.RemoveAll(outDir); err != nil { 90 fmt.Printf("%v", err) 91 os.Exit(1) 92 } 93 94 os.Exit(exitCode) 95 } 96 97 func copyFile(t *testing.T, srcFileName, destFileName string) error { 98 t.Helper() 99 from, err := os.Open(srcFileName) 100 if err != nil { 101 return err 102 } 103 defer from.Close() 104 to, err := os.Create(destFileName) 105 if err != nil { 106 return err 107 } 108 defer to.Close() 109 _, err = io.Copy(to, from) 110 return err 111 } 112 113 func imageFileNames(t *testing.T, dir string) []string { 114 t.Helper() 115 fn, err := model.ImageFileNames(dir, types.MB) 116 if err != nil { 117 t.Fatal(err) 118 } 119 sort.Strings(fn) 120 return fn 121 } 122 123 func BenchmarkValidate(b *testing.B) { 124 msg := "BenchmarkValidate" 125 b.ResetTimer() 126 for n := 0; n < b.N; n++ { 127 f, err := os.Open(filepath.Join(inDir, "gobook.0.pdf")) 128 if err != nil { 129 b.Fatalf("%s: %v\n", msg, err) 130 } 131 if err = api.Validate(f, nil); err != nil { 132 b.Fatalf("%s: %v\n", msg, err) 133 } 134 if err = f.Close(); err != nil { 135 b.Fatalf("%s: %v\n", msg, err) 136 } 137 } 138 } 139 140 func isPDF(filename string) bool { 141 return strings.HasSuffix(strings.ToLower(filename), ".pdf") 142 } 143 144 func AllPDFs(t *testing.T, dir string) []string { 145 t.Helper() 146 files, err := os.ReadDir(dir) 147 if err != nil { 148 t.Fatalf("pdfFiles from %s: %v\n", dir, err) 149 } 150 ff := []string(nil) 151 for _, f := range files { 152 if isPDF(f.Name()) { 153 ff = append(ff, f.Name()) 154 } 155 } 156 return ff 157 } 158 159 func TestPageCount(t *testing.T) { 160 msg := "TestPageCount" 161 162 fn := "5116.DCT_Filter.pdf" 163 wantPageCount := 52 164 inFile := filepath.Join(inDir, fn) 165 166 // Retrieve page count for inFile. 167 gotPageCount, err := api.PageCountFile(inFile) 168 if err != nil { 169 t.Fatalf("%s: %v\n", msg, err) 170 } 171 172 if wantPageCount != gotPageCount { 173 t.Fatalf("%s %s: pageCount want:%d got:%d\n", msg, inFile, wantPageCount, gotPageCount) 174 } 175 } 176 177 func TestPageDimensions(t *testing.T) { 178 msg := "TestPageDimensions" 179 for _, fn := range AllPDFs(t, inDir) { 180 inFile := filepath.Join(inDir, fn) 181 182 // Retrieve page dimensions for inFile. 183 if _, err := api.PageDimsFile(inFile); err != nil { 184 t.Fatalf("%s: %v\n", msg, err) 185 } 186 } 187 } 188 189 func TestValidate(t *testing.T) { 190 msg := "TestValidate" 191 inFile := filepath.Join(inDir, "Acroforms2.pdf") 192 193 //log.SetDefaultStatsLogger() 194 195 // Validate inFile. 196 if err := api.ValidateFile(inFile, nil); err != nil { 197 t.Fatalf("%s: %v\n", msg, err) 198 } 199 } 200 201 func TestManipulateContext(t *testing.T) { 202 msg := "TestManipulateContext" 203 inFile := filepath.Join(inDir, "5116.DCT_Filter.pdf") 204 outFile := filepath.Join(outDir, "abc.pdf") 205 206 // Read a PDF Context from inFile. 207 ctx, err := api.ReadContextFile(inFile) 208 if err != nil { 209 t.Fatalf("%s: ReadContextFile %s: %v\n", msg, inFile, err) 210 } 211 212 // Manipulate the PDF Context. 213 // Eg. Let's stamp all pages with pageCount and current timestamp. 214 text := fmt.Sprintf("Pages: %d \n Current time: %v", ctx.PageCount, time.Now()) 215 wm, err := api.TextWatermark(text, "font:Times-Italic, scale:.9", true, false, types.POINTS) 216 if err != nil { 217 t.Fatalf("%s: ParseTextWatermarkDetails: %v\n", msg, err) 218 } 219 if err := pdfcpu.AddWatermarks(ctx, nil, wm); err != nil { 220 t.Fatalf("%s: WatermarkContext: %v\n", msg, err) 221 } 222 223 // Write the manipulated PDF context to outFile. 224 if err := api.WriteContextFile(ctx, outFile); err != nil { 225 t.Fatalf("%s: WriteContextFile %s: %v\n", msg, outFile, err) 226 } 227 } 228 229 func TestInfo(t *testing.T) { 230 msg := "TestInfo" 231 inFile := filepath.Join(inDir, "5116.DCT_Filter.pdf") 232 233 f, err := os.Open(inFile) 234 if err != nil { 235 t.Fatalf("%s: %v\n", msg, err) 236 } 237 defer f.Close() 238 239 info, err := api.PDFInfo(f, inFile, nil, true, conf) 240 if err != nil { 241 t.Fatalf("%s: %v\n", msg, err) 242 } 243 if info == nil { 244 t.Fatalf("%s: missing Info\n", msg) 245 } 246 }