diff options
| -rw-r--r-- | compare.go | 144 | ||||
| -rw-r--r-- | fpdf_test.go | 11 | ||||
| -rw-r--r-- | internal/example/example.go | 52 | 
3 files changed, 175 insertions, 32 deletions
| diff --git a/compare.go b/compare.go new file mode 100644 index 0000000..dadf5eb --- /dev/null +++ b/compare.go @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2015 Kurt Jung (Gmail: kurt.w.jung) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package gofpdf + +import ( +	"bytes" +	"fmt" +	"io" +	"io/ioutil" +	"regexp" +) + +var ( +	// 00000230  44 46 20 31 2e 37 29 0a  2f 43 72 65 61 74 69 6f  |DF 1.7)./Creatio| +	// 00000240  6e 44 61 74 65 20 28 44  3a 32 30 31 35 31 30 30  |nDate (D:2015100| +	// 00000250  38 31 32 33 30 34 35 29  0a 3e 3e 0a 65 6e 64 6f  |8123045).>>.endo| +	creationDateRe = regexp.MustCompile("/CreationDate \\(D:\\d{14}\\)") +	fixDate        = []byte("/CreationDate (D:20000101000000)") +) + +func writeBytes(leadStr string, startPos int, sl []byte) { +	var pos, max int +	var b byte +	fmt.Printf("%s %07x", leadStr, startPos) +	max = len(sl) +	for pos < max { +		fmt.Printf(" ") +		for k := 0; k < 8; k++ { +			if pos < max { +				fmt.Printf(" %02x", sl[pos]) +			} else { +				fmt.Printf("   ") +			} +			pos++ +		} +	} +	fmt.Printf("  |") +	pos = 0 +	for pos < max { +		b = sl[pos] +		if b < 32 || b >= 128 { +			b = '.' +		} +		fmt.Printf("%c", b) +		pos++ +	} +	fmt.Printf("|\n") +} + +func checkBytes(pos int, sl1, sl2 []byte) (eq bool) { +	eq = bytes.Equal(sl1, sl2) +	if !eq { +		// 		fmt.Printf("< %v\n", sl1) +		// 		fmt.Printf("> %v\n", sl2) +		writeBytes("<", pos, sl1) +		writeBytes(">", pos, sl2) +	} +	return +} + +// compareBytes compares the bytes referred to by sl1 with those referred to by +// sl2. The comparison is done byte-for-byte with the exception of the +// CreationDate fields which are effectively ignored. Nil is returned if the +// buffers are equal, otherwise an error. +func compareBytes(sl1, sl2 []byte) (err error) { +	var posStart, posEnd, len1, len2, length int +	var diffs bool + +	sl1 = creationDateRe.ReplaceAll(sl1, fixDate) +	sl2 = creationDateRe.ReplaceAll(sl2, fixDate) +	len1 = len(sl1) +	len2 = len(sl2) +	length = len1 +	if length > len2 { +		length = len2 +	} +	// fmt.Printf("Len 1 %d, Len 2 %d, Len %d\n", len1, len2, length) +	for posStart < length-1 { +		posEnd = posStart + 16 +		if posEnd > length { +			posEnd = length +		} +		// fmt.Printf("%d to %d\n", posStart, posEnd) +		if !checkBytes(posStart, sl1[posStart:posEnd], sl2[posStart:posEnd]) { +			diffs = true +		} +		posStart = posEnd +	} +	if diffs { +		err = fmt.Errorf("documents are different") +	} +	return +} + +// ComparePDFs reads and compares the full contents of the two specified +// readers. The comparison is done byte-for-byte with the exception of the +// CreationDate fields which are effectively ignored. Nil is returned if the +// buffers are equal, otherwise an error. +func ComparePDFs(rdr1, rdr2 io.Reader) (err error) { +	var b1, b2 *bytes.Buffer +	_, err = b1.ReadFrom(rdr1) +	if err == nil { +		_, err = b2.ReadFrom(rdr2) +		if err == nil { +			err = compareBytes(b1.Bytes(), b2.Bytes()) +		} +	} +	return +} + +// ComparePDFFiles reads and compares the full contents of the two specified +// files. The comparison is done byte-for-byte with the exception of the +// CreationDate fields which are effectively ignored. Nil is returned if the +// file contents are equal, or if the second file is missing, otherwise an +// error. +func ComparePDFFiles(file1Str, file2Str string) (err error) { +	var sl1, sl2 []byte +	// fmt.Printf("Comparing [%s] with [%s]\n", file1Str, file2Str) +	sl1, err = ioutil.ReadFile(file1Str) +	if err == nil { +		sl2, err = ioutil.ReadFile(file2Str) +		if err == nil { +			err = compareBytes(sl1, sl2) +		} else { +			// Second file is missing; treat this as success +			err = nil +		} +	} +	return +} diff --git a/fpdf_test.go b/fpdf_test.go index 966767f..e45f966 100644 --- a/fpdf_test.go +++ b/fpdf_test.go @@ -40,9 +40,14 @@ func init() {  func cleanup() {  	filepath.Walk(example.PdfDir(),  		func(path string, info os.FileInfo, err error) (reterr error) { -			if len(path) > 3 { -				if path[len(path)-4:] == ".pdf" { -					os.Remove(path) +			if info.Mode().IsRegular() { +				dir, _ := filepath.Split(path) +				if "reference" != filepath.Base(dir) { +					if len(path) > 3 { +						if path[len(path)-4:] == ".pdf" { +							os.Remove(path) +						} +					}  				}  			}  			return diff --git a/internal/example/example.go b/internal/example/example.go index 9e2c736..b95972c 100644 --- a/internal/example/example.go +++ b/internal/example/example.go @@ -18,13 +18,14 @@  package example  import ( -	"bytes"  	"fmt" -	"io/ioutil" +	//	"io/ioutil"  	"os"  	"path/filepath"  	"regexp"  	"strings" + +	"github.com/jung-kurt/gofpdf"  )  var gofpdfDir string @@ -39,8 +40,7 @@ func setRoot() {  	wdStr, err := os.Getwd()  	if err == nil {  		gofpdfDir = "" -		sepStr := string(os.PathSeparator) -		list := strings.Split(wdStr, sepStr) +		list := strings.Split(filepath.ToSlash(wdStr), "/")  		for j := len(list) - 1; j >= 0 && list[j] != "gofpdf"; j-- {  			gofpdfDir = filepath.Join(gofpdfDir, "..")  		} @@ -103,38 +103,32 @@ var (  // compared except for the value of the /CreationDate field in the PDF. An  // error is returned if the two files do not match. If the reference file does  // not exist, a copy of the specified file is made and a non-nil error is -// returned only if this copy fails. +// returned only if this copy fails. If the reference file exists but has zero +// length, the file will not be overwritten and will be considered to be equal +// to the example file. This is intended to facilitate initial example +// development.  func referenceCompare(fileStr string) (err error) { -	var fileBuf, refFileBuf []byte  	var refFileStr, refDirStr, dirStr, baseFileStr string +	// var fileBuf []byte +	// var info os.FileInfo  	dirStr, baseFileStr = filepath.Split(fileStr)  	refDirStr = filepath.Join(dirStr, "reference")  	err = os.MkdirAll(refDirStr, 0755)  	if err == nil {  		refFileStr = filepath.Join(refDirStr, baseFileStr) -		fileBuf, err = ioutil.ReadFile(fileStr) -		if err == nil { -			// Replace the creation timestamp of this PDF with a fixed value -			fileBuf = creationDateRe.ReplaceAll(fileBuf, fixDate) -			refFileBuf, err = ioutil.ReadFile(refFileStr) -			if err == nil { -				if len(fileBuf) == len(refFileBuf) { -					if bytes.Equal(fileBuf, refFileBuf) { -						// Files match -					} else { -						err = fmt.Errorf("%s differs from %s", fileStr, refFileStr) -					} -				} else { -					err = fmt.Errorf("size of %s (%d) does not match size of %s (%d)", -						fileStr, len(fileBuf), refFileStr, len(refFileBuf)) -				} -			} else { -				// Reference file is missing. Create it with a copy of the newly produced -				// file in which the creation date has been fixed. Overwrite error with copy -				// error. -				err = ioutil.WriteFile(refFileStr, fileBuf, 0644) -			} -		} +		// info, err = os.Stat(refFileStr) +		// if err == nil { +		//	if info.Size() > 0 { +		err = gofpdf.ComparePDFFiles(fileStr, refFileStr) +		//	} +		// 		} else { +		// 			// Reference file is missing. Create it with a copy of the example file. +		// 			// Overwrite error with copy error. +		// 			fileBuf, err = ioutil.ReadFile(fileStr) +		// 			if err == nil { +		// 				err = ioutil.WriteFile(refFileStr, fileBuf, 0644) +		// 			} +		// 		}  	}  	return  } | 
