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 } |