ifd_builder.go: No longer use ITEVRs

This was an early way of resolving tag values that is now obsolete.
`ValueContext` structs should be used, and these, in many cases, should
be able to be constructed from the current context without passing
additional arguments.

- ifd_builder_test.go: Refactors to several tests due to loss of ITEVR support.
- ifd_builder_encode_test.go: Moved test-IB populate to testing_common.go .
- ifd_builder.go: Fixed test naming (in most cases, omitted type name).
pull/28/head
Dustin Oprea 2020-01-01 00:16:11 -05:00
parent 9946007f05
commit 88612c1cf8
4 changed files with 305 additions and 315 deletions

View File

@ -222,8 +222,8 @@ type IfdBuilder struct {
byteOrder binary.ByteOrder
// Includes both normal tags and IFD tags (which point to child IFDs).
// TODO(dustin): Keep a separate list of children like with IFd.
// TODO(dustin): Either rename this or `Entries` in Ifd to be the same thing.
// TODO(dustin): Keep a separate list of children like with `Ifd`.
// TODO(dustin): Either rename this or `Entries` in `Ifd` to be the same thing.
tags []*BuilderTag
// existingOffset will be the offset that this IFD is currently found at if
@ -312,7 +312,7 @@ func NewIfdBuilderWithExistingIfd(ifd *Ifd) (ib *IfdBuilder) {
// NewIfdBuilderFromExistingChain creates a chain of IB instances from an
// IFD chain generated from real data.
func NewIfdBuilderFromExistingChain(rootIfd *Ifd, itevr *IfdTagEntryValueResolver) (firstIb *IfdBuilder) {
// TODO(dustin): !! When we actually write the code to flatten the IB to bytes, make sure to skip the tags that have a nil value (which will happen when we add-from-exsting without a resolver instance).
// OBSOLETE(dustin): Support for `itevr` is now obsolete. This parameter will be removed in the future.
var lastIb *IfdBuilder
i := 0
@ -324,7 +324,7 @@ func NewIfdBuilderFromExistingChain(rootIfd *Ifd, itevr *IfdTagEntryValueResolve
lastIb.SetNextIb(newIb)
}
err := newIb.AddTagsFromExisting(thisExistingIfd, itevr, nil, nil)
err := newIb.AddTagsFromExisting(thisExistingIfd, nil, nil, nil)
log.PanicIf(err)
lastIb = newIb
@ -1028,6 +1028,8 @@ func (ib *IfdBuilder) AddTagsFromExisting(ifd *Ifd, itevr *IfdTagEntryValueResol
}
}()
// OBSOLETE(dustin): Support for `itevr` is now obsolete. This parameter will be removed in the future.
thumbnailData, err := ifd.Thumbnail()
if err == nil {
err = ib.SetThumbnail(thumbnailData)
@ -1078,105 +1080,76 @@ func (ib *IfdBuilder) AddTagsFromExisting(ifd *Ifd, itevr *IfdTagEntryValueResol
// If we want to add an IFD tag, we'll have to build it first and
// *then* add it via a different method.
if itevr == nil {
// We don't have any ability to resolve the structure of the
// child-IFD. Just install it as a normal tag rather than a
// fully-structured child-IFD. We're going to blank the value,
// though, since its original offset will no longer be valid
// (nor does it matter since this is just a temporary
// placeholder, in this situation).
value := NewIfdBuilderTagValueFromBytes([]byte{0, 0, 0, 0})
bt = NewBuilderTag(
ite.IfdPath,
ite.TagId,
ite.TagType,
value,
ib.byteOrder)
} else {
// Figure out which of the child-IFDs that are associated with
// this IFD represents this specific child IFD.
// Figure out which of the child-IFDs that are associated with
// this IFD represents this specific child IFD.
var childIfd *Ifd
for _, thisChildIfd := range ifd.Children {
if thisChildIfd.ParentTagIndex != i {
continue
} else if thisChildIfd.TagId != 0xffff && thisChildIfd.TagId != ite.TagId {
log.Panicf("child-IFD tag is not correct: TAG-POSITION=(%d) ITE=%s CHILD-IFD=%s", thisChildIfd.ParentTagIndex, ite, thisChildIfd)
}
childIfd = thisChildIfd
break
var childIfd *Ifd
for _, thisChildIfd := range ifd.Children {
if thisChildIfd.ParentTagIndex != i {
continue
} else if thisChildIfd.TagId != 0xffff && thisChildIfd.TagId != ite.TagId {
log.Panicf("child-IFD tag is not correct: TAG-POSITION=(%d) ITE=%s CHILD-IFD=%s", thisChildIfd.ParentTagIndex, ite, thisChildIfd)
}
if childIfd == nil {
childTagIds := make([]string, len(ifd.Children))
for j, childIfd := range ifd.Children {
childTagIds[j] = fmt.Sprintf("0x%04x (parent tag-position %d)", childIfd.TagId, childIfd.ParentTagIndex)
}
log.Panicf("could not find child IFD for child ITE: IFD-PATH=[%s] TAG-ID=(0x%04x) CURRENT-TAG-POSITION=(%d) CHILDREN=%v", ite.IfdPath, ite.TagId, i, childTagIds)
}
childIb := NewIfdBuilderFromExistingChain(childIfd, itevr)
bt = ib.NewBuilderTagFromBuilder(childIb)
childIfd = thisChildIfd
break
}
if childIfd == nil {
childTagIds := make([]string, len(ifd.Children))
for j, childIfd := range ifd.Children {
childTagIds[j] = fmt.Sprintf("0x%04x (parent tag-position %d)", childIfd.TagId, childIfd.ParentTagIndex)
}
log.Panicf("could not find child IFD for child ITE: IFD-PATH=[%s] TAG-ID=(0x%04x) CURRENT-TAG-POSITION=(%d) CHILDREN=%v", ite.IfdPath, ite.TagId, i, childTagIds)
}
childIb := NewIfdBuilderFromExistingChain(childIfd, nil)
bt = ib.NewBuilderTagFromBuilder(childIb)
} else {
// Non-IFD tag.
var value *IfdBuilderTagValue
// TODO(dustin): !! We should be able to dump (i.e. deimplement) the concept of itevr's and exclusively use ValueContext, now.
valueContext := newValueContextFromTag(
ite,
ifd.addressableData,
ifd.ByteOrder)
if itevr == nil {
// TODO(dustin): !! This might not make sense. The undefined-type data will just likely now have invalid value.
var rawBytes []byte
// rawValueOffsetCopy is our own private copy of the original data.
// It should always be four-bytes, but just copy whatever there is.
rawValueOffsetCopy := make([]byte, len(ite.RawValueOffset))
copy(rawValueOffsetCopy, ite.RawValueOffset)
if ite.TagType == TypeUndefined {
// It's an undefined-type value. Try to process, or skip if
// we don't know how to.
value = NewIfdBuilderTagValueFromBytes(rawValueOffsetCopy)
} else {
valueContext := newValueContextFromTag(
ite,
ifd.addressableData,
ifd.ByteOrder)
x, err := valueContext.Undefined()
log.PanicIf(err)
var rawBytes []byte
// TODO(dustin): !! Add test for this.
_, isUnknownUndefined := x.(TagUnknownType_UnknownValue)
if ite.TagType == TypeUndefined {
// It's an undefined-type value. Try to process, or skip if
// we don't know how to.
x, err := valueContext.Undefined()
log.PanicIf(err)
// TODO(dustin): !! Add test for this.
_, isUnknownUndefined := x.(TagUnknownType_UnknownValue)
if isUnknownUndefined == true {
continue
}
undefined, ok := x.(UnknownTagValue)
if ok != true {
log.Panicf("unexpected value returned from undefined-value processor")
}
rawBytes, err = undefined.ValueBytes()
log.PanicIf(err)
} else {
// It's a value with a standard type.
var err error
rawBytes, err = valueContext.readRawEncoded()
log.PanicIf(err)
if isUnknownUndefined == true {
continue
}
value = NewIfdBuilderTagValueFromBytes(rawBytes)
undefined, ok := x.(UnknownTagValue)
if ok != true {
log.Panicf("unexpected value returned from undefined-value processor")
}
rawBytes, err = undefined.ValueBytes()
log.PanicIf(err)
} else {
// It's a value with a standard type.
var err error
rawBytes, err = valueContext.readRawEncoded()
log.PanicIf(err)
}
value = NewIfdBuilderTagValueFromBytes(rawBytes)
bt = NewBuilderTag(
ifd.IfdPath,
ite.TagId,

View File

@ -3,7 +3,6 @@ package exif
import (
"bytes"
"fmt"
"reflect"
"strings"
"testing"
@ -562,97 +561,6 @@ func Test_IfdByteEncoder_encodeTagToBytes_simpleTag_allocate(t *testing.T) {
}
}
func getExifSimpleTestIb() *IfdBuilder {
im := NewIfdMapping()
err := LoadStandardIfds(im)
log.PanicIf(err)
ti := NewTagIndex()
ib := NewIfdBuilder(im, ti, IfdPathStandard, TestDefaultByteOrder)
err = ib.AddStandard(0x000b, "asciivalue")
log.PanicIf(err)
err = ib.AddStandard(0x00ff, []uint16{0x1122})
log.PanicIf(err)
err = ib.AddStandard(0x0100, []uint32{0x33445566})
log.PanicIf(err)
err = ib.AddStandard(0x013e, []Rational{{Numerator: 0x11112222, Denominator: 0x33334444}})
log.PanicIf(err)
return ib
}
func validateExifSimpleTestIb(exifData []byte, t *testing.T) {
im := NewIfdMapping()
err := LoadStandardIfds(im)
log.PanicIf(err)
ti := NewTagIndex()
eh, index, err := Collect(im, ti, exifData)
log.PanicIf(err)
if eh.ByteOrder != TestDefaultByteOrder {
t.Fatalf("EXIF byte-order is not correct: %v", eh.ByteOrder)
} else if eh.FirstIfdOffset != ExifDefaultFirstIfdOffset {
t.Fatalf("EXIF first IFD-offset not correct: (0x%02x)", eh.FirstIfdOffset)
}
if len(index.Ifds) != 1 {
t.Fatalf("There wasn't exactly one IFD decoded: (%d)", len(index.Ifds))
}
ifd := index.RootIfd
if ifd.ByteOrder != TestDefaultByteOrder {
t.Fatalf("IFD byte-order not correct.")
} else if ifd.IfdPath != IfdStandard {
t.Fatalf("IFD name not correct.")
} else if ifd.Index != 0 {
t.Fatalf("IFD index not zero: (%d)", ifd.Index)
} else if ifd.Offset != uint32(0x0008) {
t.Fatalf("IFD offset not correct.")
} else if len(ifd.Entries) != 4 {
t.Fatalf("IFD number of entries not correct: (%d)", len(ifd.Entries))
} else if ifd.NextIfdOffset != uint32(0) {
t.Fatalf("Next-IFD offset is non-zero.")
} else if ifd.NextIfd != nil {
t.Fatalf("Next-IFD pointer is non-nil.")
}
// Verify the values by using the actual, orginal types (this is awesome).
addressableData := exifData[ExifAddressableAreaStart:]
expected := []struct {
tagId uint16
value interface{}
}{
{tagId: 0x000b, value: "asciivalue"},
{tagId: 0x00ff, value: []uint16{0x1122}},
{tagId: 0x0100, value: []uint32{0x33445566}},
{tagId: 0x013e, value: []Rational{{Numerator: 0x11112222, Denominator: 0x33334444}}},
}
for i, e := range ifd.Entries {
if e.TagId != expected[i].tagId {
t.Fatalf("Tag-ID for entry (%d) not correct: (0x%02x) != (0x%02x)", i, e.TagId, expected[i].tagId)
}
value, err := e.Value(addressableData, TestDefaultByteOrder)
log.PanicIf(err)
if reflect.DeepEqual(value, expected[i].value) != true {
t.Fatalf("Value for entry (%d) not correct: [%v] != [%v]", i, value, expected[i].value)
}
}
}
func Test_IfdByteEncoder_encodeIfdToBytes_simple(t *testing.T) {
ib := getExifSimpleTestIb()

View File

@ -11,7 +11,7 @@ import (
"github.com/dsoprea/go-logging"
)
func TestAdd(t *testing.T) {
func TestIfdBuilder_Add(t *testing.T) {
im := NewIfdMapping()
err := LoadStandardIfds(im)
@ -103,7 +103,7 @@ func TestAdd(t *testing.T) {
}
}
func TestSetNextIb(t *testing.T) {
func TestIfdBuilder_SetNextIb(t *testing.T) {
im := NewIfdMapping()
err := LoadStandardIfds(im)
@ -128,7 +128,7 @@ func TestSetNextIb(t *testing.T) {
}
}
func TestAddChildIb(t *testing.T) {
func TestIfdBuilder_AddChildIb(t *testing.T) {
im := NewIfdMapping()
err := LoadStandardIfds(im)
@ -172,160 +172,120 @@ func TestAddChildIb(t *testing.T) {
}
}
func TestAddTagsFromExisting(t *testing.T) {
func TestIfdBuilder_AddTagsFromExisting(t *testing.T) {
defer func() {
if state := recover(); state != nil {
err := log.Wrap(state.(error))
log.PrintErrorf(err, "Test failure.")
log.PrintError(err)
t.Fatalf("Test failure.")
}
}()
exifData := getExifSimpleTestIbBytes()
im := NewIfdMapping()
err := LoadStandardIfds(im)
log.PanicIf(err)
ti := NewTagIndex()
ib := NewIfdBuilder(im, ti, IfdPathStandard, TestDefaultByteOrder)
entries := make([]*IfdTagEntry, 3)
entries[0] = &IfdTagEntry{
IfdPath: IfdPathStandardExif,
TagId: 0x11,
TagType: TypeByte,
UnitCount: 4,
RawValueOffset: []byte{0x12, 0, 0, 0},
}
entries[1] = &IfdTagEntry{
IfdPath: IfdPathStandardExif,
TagId: 0x22,
TagType: TypeLong,
ChildIfdPath: "some ifd",
}
entries[2] = &IfdTagEntry{
IfdPath: IfdPathStandardExif,
TagId: 0x33,
TagType: TypeByte,
UnitCount: 4,
RawValueOffset: []byte{0x34, 0, 0, 0},
}
ifd := &Ifd{
IfdPath: IfdPathStandard,
Entries: entries,
tagIndex: ti,
}
err = ib.AddTagsFromExisting(ifd, nil, nil, nil)
_, index, err := Collect(im, ti, exifData)
log.PanicIf(err)
if ib.tags[0].tagId != 0x11 {
t.Fatalf("tag (0) not correct")
} else if ib.tags[1].tagId != 0x22 {
t.Fatalf("tag (1) not correct")
} else if ib.tags[2].tagId != 0x33 {
t.Fatalf("tag (2) not correct")
} else if len(ib.tags) != 3 {
t.Fatalf("tag count not correct")
ib := NewIfdBuilder(im, ti, IfdPathStandard, TestDefaultByteOrder)
err = ib.AddTagsFromExisting(index.RootIfd, nil, nil, nil)
log.PanicIf(err)
expected := []uint16{
0x000b,
0x00ff,
0x0100,
0x013e,
}
if len(ib.tags) != len(expected) {
t.Fatalf("Tag count not correct: (%d) != (%d)", len(ib.tags), len(expected))
}
for i, tag := range ib.tags {
if tag.tagId != expected[i] {
t.Fatalf("Tag (%d) not correct: (0x%04x) != (0x%04x)", i, tag.tagId, expected[i])
}
}
}
func TestAddTagsFromExisting__Includes(t *testing.T) {
func TestIfdBuilder_AddTagsFromExisting__Includes(t *testing.T) {
exifData := getExifSimpleTestIbBytes()
im := NewIfdMapping()
err := LoadStandardIfds(im)
log.PanicIf(err)
ti := NewTagIndex()
ib := NewIfdBuilder(im, ti, IfdPathStandard, TestDefaultByteOrder)
entries := make([]*IfdTagEntry, 3)
entries[0] = &IfdTagEntry{
IfdPath: IfdPathStandard,
TagType: TypeByte,
TagId: 0x11,
}
entries[1] = &IfdTagEntry{
IfdPath: IfdPathStandard,
TagType: TypeByte,
TagId: 0x22,
ChildIfdPath: "some ifd",
}
entries[2] = &IfdTagEntry{
IfdPath: IfdPathStandard,
TagType: TypeByte,
TagId: 0x33,
}
ifd := &Ifd{
IfdPath: IfdPathStandard,
Entries: entries,
tagIndex: ti,
}
err = ib.AddTagsFromExisting(ifd, nil, []uint16{0x33}, nil)
_, index, err := Collect(im, ti, exifData)
log.PanicIf(err)
if ib.tags[0].tagId != 0x33 {
t.Fatalf("tag (1) not correct")
} else if len(ib.tags) != 1 {
t.Fatalf("tag count not correct")
ib := NewIfdBuilder(im, ti, IfdPathStandard, TestDefaultByteOrder)
err = ib.AddTagsFromExisting(index.RootIfd, nil, []uint16{0x00ff}, nil)
log.PanicIf(err)
expected := []uint16{
0x00ff,
}
if len(ib.tags) != len(expected) {
t.Fatalf("Tag count not correct: (%d) != (%d)", len(ib.tags), len(expected))
}
for i, tag := range ib.tags {
if tag.tagId != expected[i] {
t.Fatalf("Tag (%d) not correct: (0x%04x) != (0x%04x)", i, tag.tagId, expected[i])
}
}
}
func TestAddTagsFromExisting__Excludes(t *testing.T) {
func TestIfdBuilder_AddTagsFromExisting__Excludes(t *testing.T) {
exifData := getExifSimpleTestIbBytes()
im := NewIfdMapping()
err := LoadStandardIfds(im)
log.PanicIf(err)
ti := NewTagIndex()
ib := NewIfdBuilder(im, ti, IfdPathStandard, TestDefaultByteOrder)
entries := make([]*IfdTagEntry, 3)
entries[0] = &IfdTagEntry{
IfdPath: IfdPathStandard,
TagType: TypeByte,
TagId: 0x11,
}
entries[1] = &IfdTagEntry{
IfdPath: IfdPathStandard,
TagType: TypeByte,
TagId: 0x22,
ChildIfdPath: "some ifd",
}
entries[2] = &IfdTagEntry{
IfdPath: IfdPathStandard,
TagType: TypeByte,
TagId: 0x33,
}
ifd := &Ifd{
IfdPath: IfdPathStandard,
Entries: entries,
tagIndex: ti,
}
err = ib.AddTagsFromExisting(ifd, nil, nil, []uint16{0x11})
_, index, err := Collect(im, ti, exifData)
log.PanicIf(err)
if ib.tags[0].tagId != 0x22 {
t.Fatalf("tag not correct")
} else if len(ib.tags) != 2 {
t.Fatalf("tag count not correct")
ib := NewIfdBuilder(im, ti, IfdPathStandard, TestDefaultByteOrder)
err = ib.AddTagsFromExisting(index.RootIfd, nil, nil, []uint16{0xff})
log.PanicIf(err)
expected := []uint16{
0x000b,
0x0100,
0x013e,
}
if len(ib.tags) != len(expected) {
t.Fatalf("Tag count not correct: (%d) != (%d)", len(ib.tags), len(expected))
}
for i, tag := range ib.tags {
if tag.tagId != expected[i] {
t.Fatalf("Tag (%d) not correct: (0x%04x) != (0x%04x)", i, tag.tagId, expected[i])
}
}
}
func TestFindN_First_1(t *testing.T) {
func TestIfdBuilder_FindN__First_1(t *testing.T) {
im := NewIfdMapping()
err := LoadStandardIfds(im)
@ -381,7 +341,7 @@ func TestFindN_First_1(t *testing.T) {
}
}
func TestFindN_First_2_1Returned(t *testing.T) {
func TestIfdBuilder_FindN__First_2_1Returned(t *testing.T) {
im := NewIfdMapping()
err := LoadStandardIfds(im)
@ -437,7 +397,7 @@ func TestFindN_First_2_1Returned(t *testing.T) {
}
}
func TestFindN_First_2_2Returned(t *testing.T) {
func TestIfdBuilder_FindN__First_2_2Returned(t *testing.T) {
im := NewIfdMapping()
err := LoadStandardIfds(im)
@ -520,7 +480,7 @@ func TestFindN_First_2_2Returned(t *testing.T) {
}
}
func TestFindN_Middle_WithDuplicates(t *testing.T) {
func TestIfdBuilder_FindN__Middle_WithDuplicates(t *testing.T) {
im := NewIfdMapping()
err := LoadStandardIfds(im)
@ -606,7 +566,7 @@ func TestFindN_Middle_WithDuplicates(t *testing.T) {
}
}
func TestFindN_Middle_NoDuplicates(t *testing.T) {
func TestIfdBuilder_FindN__Middle_NoDuplicates(t *testing.T) {
im := NewIfdMapping()
err := LoadStandardIfds(im)
@ -672,7 +632,7 @@ func TestFindN_Middle_NoDuplicates(t *testing.T) {
}
}
func TestFindN_Miss(t *testing.T) {
func TestIfdBuilder_FindN__Miss(t *testing.T) {
im := NewIfdMapping()
err := LoadStandardIfds(im)
@ -689,7 +649,7 @@ func TestFindN_Miss(t *testing.T) {
}
}
func TestFind_Hit(t *testing.T) {
func TestIfdBuilder_Find__Hit(t *testing.T) {
im := NewIfdMapping()
err := LoadStandardIfds(im)
@ -753,7 +713,7 @@ func TestFind_Hit(t *testing.T) {
}
}
func TestFind_Miss(t *testing.T) {
func TestIfdBuilder_Find__Miss(t *testing.T) {
im := NewIfdMapping()
err := LoadStandardIfds(im)
@ -810,7 +770,7 @@ func TestFind_Miss(t *testing.T) {
}
}
func TestReplace(t *testing.T) {
func TestIfdBuilder_Replace(t *testing.T) {
im := NewIfdMapping()
err := LoadStandardIfds(im)
@ -878,7 +838,7 @@ func TestReplace(t *testing.T) {
}
}
func TestReplaceN(t *testing.T) {
func TestIfdBuilder_ReplaceN(t *testing.T) {
im := NewIfdMapping()
err := LoadStandardIfds(im)
@ -946,7 +906,7 @@ func TestReplaceN(t *testing.T) {
}
}
func TestDeleteFirst(t *testing.T) {
func TestIfdBuilder_DeleteFirst(t *testing.T) {
im := NewIfdMapping()
err := LoadStandardIfds(im)
@ -1048,7 +1008,7 @@ func TestDeleteFirst(t *testing.T) {
}
}
func TestDeleteN(t *testing.T) {
func TestIfdBuilder_DeleteN(t *testing.T) {
im := NewIfdMapping()
err := LoadStandardIfds(im)
@ -1150,7 +1110,7 @@ func TestDeleteN(t *testing.T) {
}
}
func TestDeleteN_Two(t *testing.T) {
func TestIfdBuilder_DeleteN_Two(t *testing.T) {
im := NewIfdMapping()
err := LoadStandardIfds(im)
@ -1236,7 +1196,7 @@ func TestDeleteN_Two(t *testing.T) {
}
}
func TestDeleteAll(t *testing.T) {
func TestIfdBuilder_DeleteAll(t *testing.T) {
im := NewIfdMapping()
err := LoadStandardIfds(im)
@ -1324,7 +1284,7 @@ func TestDeleteAll(t *testing.T) {
}
}
func Test_IfdBuilder_CreateIfdBuilderFromExistingChain(t *testing.T) {
func TestIfdBuilder_CreateIfdBuilderFromExistingChain(t *testing.T) {
defer func() {
if state := recover(); state != nil {
err := log.Wrap(state.(error))
@ -1427,7 +1387,7 @@ func Test_IfdBuilder_CreateIfdBuilderFromExistingChain(t *testing.T) {
// TODO(dustin): !! Test with an actual GPS-attached image.
func Test_IfdBuilder_CreateIfdBuilderFromExistingChain_RealData(t *testing.T) {
func TestIfdBuilder_CreateIfdBuilderFromExistingChain_RealData(t *testing.T) {
filepath := path.Join(assetsPath, "NDM_8901.jpg")
rawExif, err := SearchFileAndExtractExif(filepath)
@ -1546,7 +1506,7 @@ func Test_IfdBuilder_CreateIfdBuilderFromExistingChain_RealData(t *testing.T) {
}
}
// func Test_IfdBuilder_CreateIfdBuilderFromExistingChain_RealData_WithUpdate(t *testing.T) {
// func TestIfdBuilder_CreateIfdBuilderFromExistingChain_RealData_WithUpdate(t *testing.T) {
// filepath := path.Join(assetsPath, "NDM_8901.jpg")
// rawExif, err := SearchFileAndExtractExif(filepath)
@ -1843,7 +1803,7 @@ func ExampleIfdBuilder_SetStandardWithName() {
// alternative software
}
func Test_IfdBuilder_CreateIfdBuilderWithExistingIfd(t *testing.T) {
func TestIfdBuilder_CreateIfdBuilderWithExistingIfd(t *testing.T) {
ti := NewTagIndex()
im := NewIfdMapping()
@ -1884,7 +1844,7 @@ func Test_IfdBuilder_CreateIfdBuilderWithExistingIfd(t *testing.T) {
}
}
func TestNewStandardBuilderTag_OneUnit(t *testing.T) {
func TestNewStandardBuilderTag__OneUnit(t *testing.T) {
ti := NewTagIndex()
it, err := ti.Get(IfdPathStandardExif, uint16(0x8833))
@ -1901,7 +1861,7 @@ func TestNewStandardBuilderTag_OneUnit(t *testing.T) {
}
}
func TestNewStandardBuilderTag_TwoUnits(t *testing.T) {
func TestNewStandardBuilderTag__TwoUnits(t *testing.T) {
ti := NewTagIndex()
it, err := ti.Get(IfdPathStandardExif, uint16(0x8833))
@ -1920,7 +1880,7 @@ func TestNewStandardBuilderTag_TwoUnits(t *testing.T) {
}
}
func TestAddStandardWithName(t *testing.T) {
func TestIfdBuilder_AddStandardWithName(t *testing.T) {
im := NewIfdMapping()
err := LoadStandardIfds(im)
@ -1951,7 +1911,7 @@ func TestAddStandardWithName(t *testing.T) {
}
}
func TestGetOrCreateIbFromRootIb_Noop(t *testing.T) {
func TestGetOrCreateIbFromRootIb__Noop(t *testing.T) {
im := NewIfdMapping()
err := LoadStandardIfds(im)
@ -1972,7 +1932,7 @@ func TestGetOrCreateIbFromRootIb_Noop(t *testing.T) {
}
}
func TestGetOrCreateIbFromRootIb_FqNoop(t *testing.T) {
func TestGetOrCreateIbFromRootIb__FqNoop(t *testing.T) {
im := NewIfdMapping()
err := LoadStandardIfds(im)
@ -2010,7 +1970,7 @@ func TestGetOrCreateIbFromRootIb_InvalidChild(t *testing.T) {
}
}
func TestGetOrCreateIbFromRootIb_Child(t *testing.T) {
func TestGetOrCreateIbFromRootIb__Child(t *testing.T) {
defer func() {
if state := recover(); state != nil {
err := log.Wrap(state.(error))

149
testing_common.go Normal file
View File

@ -0,0 +1,149 @@
package exif
import (
"reflect"
"testing"
"github.com/dsoprea/go-logging"
)
func getExifSimpleTestIb() *IfdBuilder {
defer func() {
if state := recover(); state != nil {
err := log.Wrap(state.(error))
log.Panic(err)
}
}()
im := NewIfdMapping()
err := LoadStandardIfds(im)
log.PanicIf(err)
ti := NewTagIndex()
ib := NewIfdBuilder(im, ti, IfdPathStandard, TestDefaultByteOrder)
err = ib.AddStandard(0x000b, "asciivalue")
log.PanicIf(err)
err = ib.AddStandard(0x00ff, []uint16{0x1122})
log.PanicIf(err)
err = ib.AddStandard(0x0100, []uint32{0x33445566})
log.PanicIf(err)
err = ib.AddStandard(0x013e, []Rational{{Numerator: 0x11112222, Denominator: 0x33334444}})
log.PanicIf(err)
return ib
}
func getExifSimpleTestIbBytes() []byte {
defer func() {
if state := recover(); state != nil {
err := log.Wrap(state.(error))
log.Panic(err)
}
}()
im := NewIfdMapping()
err := LoadStandardIfds(im)
log.PanicIf(err)
ti := NewTagIndex()
ib := NewIfdBuilder(im, ti, IfdPathStandard, TestDefaultByteOrder)
err = ib.AddStandard(0x000b, "asciivalue")
log.PanicIf(err)
err = ib.AddStandard(0x00ff, []uint16{0x1122})
log.PanicIf(err)
err = ib.AddStandard(0x0100, []uint32{0x33445566})
log.PanicIf(err)
err = ib.AddStandard(0x013e, []Rational{{Numerator: 0x11112222, Denominator: 0x33334444}})
log.PanicIf(err)
ibe := NewIfdByteEncoder()
exifData, err := ibe.EncodeToExif(ib)
log.PanicIf(err)
return exifData
}
func validateExifSimpleTestIb(exifData []byte, t *testing.T) {
defer func() {
if state := recover(); state != nil {
err := log.Wrap(state.(error))
log.Panic(err)
}
}()
im := NewIfdMapping()
err := LoadStandardIfds(im)
log.PanicIf(err)
ti := NewTagIndex()
eh, index, err := Collect(im, ti, exifData)
log.PanicIf(err)
if eh.ByteOrder != TestDefaultByteOrder {
t.Fatalf("EXIF byte-order is not correct: %v", eh.ByteOrder)
} else if eh.FirstIfdOffset != ExifDefaultFirstIfdOffset {
t.Fatalf("EXIF first IFD-offset not correct: (0x%02x)", eh.FirstIfdOffset)
}
if len(index.Ifds) != 1 {
t.Fatalf("There wasn't exactly one IFD decoded: (%d)", len(index.Ifds))
}
ifd := index.RootIfd
if ifd.ByteOrder != TestDefaultByteOrder {
t.Fatalf("IFD byte-order not correct.")
} else if ifd.IfdPath != IfdStandard {
t.Fatalf("IFD name not correct.")
} else if ifd.Index != 0 {
t.Fatalf("IFD index not zero: (%d)", ifd.Index)
} else if ifd.Offset != uint32(0x0008) {
t.Fatalf("IFD offset not correct.")
} else if len(ifd.Entries) != 4 {
t.Fatalf("IFD number of entries not correct: (%d)", len(ifd.Entries))
} else if ifd.NextIfdOffset != uint32(0) {
t.Fatalf("Next-IFD offset is non-zero.")
} else if ifd.NextIfd != nil {
t.Fatalf("Next-IFD pointer is non-nil.")
}
// Verify the values by using the actual, orginal types (this is awesome).
addressableData := exifData[ExifAddressableAreaStart:]
expected := []struct {
tagId uint16
value interface{}
}{
{tagId: 0x000b, value: "asciivalue"},
{tagId: 0x00ff, value: []uint16{0x1122}},
{tagId: 0x0100, value: []uint32{0x33445566}},
{tagId: 0x013e, value: []Rational{{Numerator: 0x11112222, Denominator: 0x33334444}}},
}
for i, e := range ifd.Entries {
if e.TagId != expected[i].tagId {
t.Fatalf("Tag-ID for entry (%d) not correct: (0x%02x) != (0x%02x)", i, e.TagId, expected[i].tagId)
}
value, err := e.Value(addressableData, TestDefaultByteOrder)
log.PanicIf(err)
if reflect.DeepEqual(value, expected[i].value) != true {
t.Fatalf("Value for entry (%d) not correct: [%v] != [%v]", i, value, expected[i].value)
}
}
}