Very nice looking tests!

Signed-off-by: Kris Nóva <kris@nivenly.com>
This commit is contained in:
Kris Nóva 2021-02-09 16:00:02 -08:00
parent 3b41c9dd5f
commit c1a45bf8e3
149 changed files with 1241 additions and 443 deletions

View file

@ -1,87 +1,89 @@
package pngstructure
import (
"bytes"
"fmt"
"fmt"
"bytes"
"encoding/binary"
"encoding/binary"
log "github.com/dsoprea/go-logging"
"github.com/dsoprea/go-logging"
)
type ChunkDecoder struct {
}
func NewChunkDecoder() *ChunkDecoder {
return new(ChunkDecoder)
return new(ChunkDecoder)
}
func (cd *ChunkDecoder) Decode(c *Chunk) (decoded interface{}, err error) {
defer func() {
if state := recover(); state != nil {
err := log.Wrap(state.(error))
log.Panic(err)
}
}()
defer func() {
if state := recover(); state != nil {
err := log.Wrap(state.(error))
log.Panic(err)
}
}()
switch c.Type {
case "IHDR":
ihdr, err := cd.decodeIHDR(c)
log.PanicIf(err)
switch c.Type {
case "IHDR":
ihdr, err := cd.decodeIHDR(c)
log.PanicIf(err)
return ihdr, nil
}
return ihdr, nil
}
// We don't decode this particular type.
return nil, nil
// We don't decode this particular type.
return nil, nil
}
type ChunkIHDR struct {
Width uint32
Height uint32
BitDepth uint8
ColorType uint8
CompressionMethod uint8
FilterMethod uint8
InterlaceMethod uint8
Width uint32
Height uint32
BitDepth uint8
ColorType uint8
CompressionMethod uint8
FilterMethod uint8
InterlaceMethod uint8
}
func (ihdr *ChunkIHDR) String() string {
return fmt.Sprintf("IHDR<WIDTH=(%d) HEIGHT=(%d) DEPTH=(%d) COLOR-TYPE=(%d) COMP-METHOD=(%d) FILTER-METHOD=(%d) INTRLC-METHOD=(%d)>", ihdr.Width, ihdr.Height, ihdr.BitDepth, ihdr.ColorType, ihdr.CompressionMethod, ihdr.FilterMethod, ihdr.InterlaceMethod)
return fmt.Sprintf("IHDR<WIDTH=(%d) HEIGHT=(%d) DEPTH=(%d) COLOR-TYPE=(%d) COMP-METHOD=(%d) FILTER-METHOD=(%d) INTRLC-METHOD=(%d)>", ihdr.Width, ihdr.Height, ihdr.BitDepth, ihdr.ColorType, ihdr.CompressionMethod, ihdr.FilterMethod, ihdr.InterlaceMethod)
}
func (cd *ChunkDecoder) decodeIHDR(c *Chunk) (ihdr *ChunkIHDR, err error) {
defer func() {
if state := recover(); state != nil {
err := log.Wrap(state.(error))
log.Panic(err)
}
}()
defer func() {
if state := recover(); state != nil {
err := log.Wrap(state.(error))
log.Panic(err)
}
}()
b := bytes.NewBuffer(c.Data)
b := bytes.NewBuffer(c.Data)
ihdr = new(ChunkIHDR)
ihdr = new(ChunkIHDR)
err = binary.Read(b, binary.BigEndian, &ihdr.Width)
log.PanicIf(err)
err = binary.Read(b, binary.BigEndian, &ihdr.Width)
log.PanicIf(err)
err = binary.Read(b, binary.BigEndian, &ihdr.Height)
log.PanicIf(err)
err = binary.Read(b, binary.BigEndian, &ihdr.Height)
log.PanicIf(err)
err = binary.Read(b, binary.BigEndian, &ihdr.BitDepth)
log.PanicIf(err)
err = binary.Read(b, binary.BigEndian, &ihdr.BitDepth)
log.PanicIf(err)
err = binary.Read(b, binary.BigEndian, &ihdr.ColorType)
log.PanicIf(err)
err = binary.Read(b, binary.BigEndian, &ihdr.ColorType)
log.PanicIf(err)
err = binary.Read(b, binary.BigEndian, &ihdr.CompressionMethod)
log.PanicIf(err)
err = binary.Read(b, binary.BigEndian, &ihdr.CompressionMethod)
log.PanicIf(err)
err = binary.Read(b, binary.BigEndian, &ihdr.FilterMethod)
log.PanicIf(err)
err = binary.Read(b, binary.BigEndian, &ihdr.FilterMethod)
log.PanicIf(err)
err = binary.Read(b, binary.BigEndian, &ihdr.InterlaceMethod)
log.PanicIf(err)
err = binary.Read(b, binary.BigEndian, &ihdr.InterlaceMethod)
log.PanicIf(err)
return ihdr, nil
return ihdr, nil
}

View file

@ -1,13 +1,13 @@
package pngstructure
import (
"bufio"
"bytes"
"io"
"os"
"bufio"
"bytes"
"io"
"os"
log "github.com/dsoprea/go-logging"
riimage "github.com/dsoprea/go-utility/image"
"github.com/dsoprea/go-logging"
"github.com/dsoprea/go-utility/image"
)
// PngMediaParser knows how to parse a PNG stream.
@ -17,90 +17,90 @@ type PngMediaParser struct {
// NewPngMediaParser returns a new `PngMediaParser` struct.
func NewPngMediaParser() *PngMediaParser {
// TODO(dustin): Add test
// TODO(dustin): Add test
return new(PngMediaParser)
return new(PngMediaParser)
}
// Parse parses a PNG stream given a `io.ReadSeeker`.
func (pmp *PngMediaParser) Parse(rs io.ReadSeeker, size int) (mc riimage.MediaContext, err error) {
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
}
}()
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
}
}()
// TODO(dustin): Add test
// TODO(dustin): Add test
ps := NewPngSplitter()
ps := NewPngSplitter()
err = ps.readHeader(rs)
log.PanicIf(err)
err = ps.readHeader(rs)
log.PanicIf(err)
s := bufio.NewScanner(rs)
s := bufio.NewScanner(rs)
// Since each segment can be any size, our buffer must be allowed to grow
// as large as the file.
buffer := []byte{}
s.Buffer(buffer, size)
s.Split(ps.Split)
// Since each segment can be any size, our buffer must be allowed to grow
// as large as the file.
buffer := []byte{}
s.Buffer(buffer, size)
s.Split(ps.Split)
for s.Scan() != false {
}
log.PanicIf(s.Err())
for s.Scan() != false {
}
log.PanicIf(s.Err())
return ps.Chunks(), nil
return ps.Chunks(), nil
}
// ParseFile parses a PNG stream given a file-path.
func (pmp *PngMediaParser) ParseFile(filepath string) (mc riimage.MediaContext, err error) {
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
}
}()
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
}
}()
f, err := os.Open(filepath)
log.PanicIf(err)
f, err := os.Open(filepath)
log.PanicIf(err)
defer f.Close()
defer f.Close()
stat, err := f.Stat()
log.PanicIf(err)
stat, err := f.Stat()
log.PanicIf(err)
size := stat.Size()
size := stat.Size()
chunks, err := pmp.Parse(f, int(size))
log.PanicIf(err)
chunks, err := pmp.Parse(f, int(size))
log.PanicIf(err)
return chunks, nil
return chunks, nil
}
// ParseBytes parses a PNG stream given a byte-slice.
func (pmp *PngMediaParser) ParseBytes(data []byte) (mc riimage.MediaContext, err error) {
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
}
}()
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
}
}()
// TODO(dustin): Add test
// TODO(dustin): Add test
br := bytes.NewReader(data)
br := bytes.NewReader(data)
chunks, err := pmp.Parse(br, len(data))
log.PanicIf(err)
chunks, err := pmp.Parse(br, len(data))
log.PanicIf(err)
return chunks, nil
return chunks, nil
}
// LooksLikeFormat returns a boolean indicating whether the stream looks like a
// PNG image.
func (pmp *PngMediaParser) LooksLikeFormat(data []byte) bool {
return bytes.Compare(data[:len(PngSignature)], PngSignature[:]) == 0
return bytes.Compare(data[:len(PngSignature)], PngSignature[:]) == 0
}
var (
// Enforce interface conformance.
_ riimage.MediaParser = new(PngMediaParser)
// Enforce interface conformance.
_ riimage.MediaParser = new(PngMediaParser)
)

View file

@ -10,8 +10,8 @@ import (
"hash/crc32"
"github.com/dsoprea/go-exif/v2"
log "github.com/dsoprea/go-logging"
riimage "github.com/dsoprea/go-utility/image"
"github.com/dsoprea/go-logging"
"github.com/dsoprea/go-utility/image"
)
var (

View file

@ -1,64 +1,64 @@
package pngstructure
import (
"os"
"path"
"os"
"path"
log "github.com/dsoprea/go-logging"
"github.com/dsoprea/go-logging"
)
var (
assetsPath = ""
assetsPath = ""
)
func getModuleRootPath() string {
moduleRootPath := os.Getenv("PNG_MODULE_ROOT_PATH")
if moduleRootPath != "" {
return moduleRootPath
}
moduleRootPath := os.Getenv("PNG_MODULE_ROOT_PATH")
if moduleRootPath != "" {
return moduleRootPath
}
currentWd, err := os.Getwd()
log.PanicIf(err)
currentWd, err := os.Getwd()
log.PanicIf(err)
currentPath := currentWd
visited := make([]string, 0)
currentPath := currentWd
visited := make([]string, 0)
for {
tryStampFilepath := path.Join(currentPath, ".MODULE_ROOT")
for {
tryStampFilepath := path.Join(currentPath, ".MODULE_ROOT")
_, err := os.Stat(tryStampFilepath)
if err != nil && os.IsNotExist(err) != true {
log.Panic(err)
} else if err == nil {
break
}
_, err := os.Stat(tryStampFilepath)
if err != nil && os.IsNotExist(err) != true {
log.Panic(err)
} else if err == nil {
break
}
visited = append(visited, tryStampFilepath)
visited = append(visited, tryStampFilepath)
currentPath = path.Dir(currentPath)
if currentPath == "/" {
log.Panicf("could not find module-root: %v", visited)
}
}
currentPath = path.Dir(currentPath)
if currentPath == "/" {
log.Panicf("could not find module-root: %v", visited)
}
}
return currentPath
return currentPath
}
func getTestAssetsPath() string {
if assetsPath == "" {
moduleRootPath := getModuleRootPath()
assetsPath = path.Join(moduleRootPath, "assets")
}
if assetsPath == "" {
moduleRootPath := getModuleRootPath()
assetsPath = path.Join(moduleRootPath, "assets")
}
return assetsPath
return assetsPath
}
func getTestBasicImageFilepath() string {
assetsPath := getTestAssetsPath()
return path.Join(assetsPath, "libpng.png")
assetsPath := getTestAssetsPath()
return path.Join(assetsPath, "libpng.png")
}
func getTestExifImageFilepath() string {
assetsPath := getTestAssetsPath()
return path.Join(assetsPath, "exif.png")
assetsPath := getTestAssetsPath()
return path.Join(assetsPath, "exif.png")
}

View file

@ -1,65 +1,65 @@
package pngstructure
import (
"bytes"
"fmt"
"fmt"
"bytes"
log "github.com/dsoprea/go-logging"
"github.com/dsoprea/go-logging"
)
func DumpBytes(data []byte) {
fmt.Printf("DUMP: ")
for _, x := range data {
fmt.Printf("%02x ", x)
}
fmt.Printf("DUMP: ")
for _, x := range data {
fmt.Printf("%02x ", x)
}
fmt.Printf("\n")
fmt.Printf("\n")
}
func DumpBytesClause(data []byte) {
fmt.Printf("DUMP: ")
fmt.Printf("DUMP: ")
fmt.Printf("[]byte { ")
fmt.Printf("[]byte { ")
for i, x := range data {
fmt.Printf("0x%02x", x)
for i, x := range data {
fmt.Printf("0x%02x", x)
if i < len(data)-1 {
fmt.Printf(", ")
}
}
if i < len(data) - 1 {
fmt.Printf(", ")
}
}
fmt.Printf(" }\n")
fmt.Printf(" }\n")
}
func DumpBytesToString(data []byte) string {
b := new(bytes.Buffer)
b := new(bytes.Buffer)
for i, x := range data {
_, err := b.WriteString(fmt.Sprintf("%02x", x))
log.PanicIf(err)
for i, x := range data {
_, err := b.WriteString(fmt.Sprintf("%02x", x))
log.PanicIf(err)
if i < len(data)-1 {
_, err := b.WriteRune(' ')
log.PanicIf(err)
}
}
if i < len(data) - 1 {
_, err := b.WriteRune(' ')
log.PanicIf(err)
}
}
return b.String()
return b.String()
}
func DumpBytesClauseToString(data []byte) string {
b := new(bytes.Buffer)
b := new(bytes.Buffer)
for i, x := range data {
_, err := b.WriteString(fmt.Sprintf("0x%02x", x))
log.PanicIf(err)
for i, x := range data {
_, err := b.WriteString(fmt.Sprintf("0x%02x", x))
log.PanicIf(err)
if i < len(data)-1 {
_, err := b.WriteString(", ")
log.PanicIf(err)
}
}
if i < len(data) - 1 {
_, err := b.WriteString(", ")
log.PanicIf(err)
}
}
return b.String()
return b.String()
}