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  }