ifd_builder: Added tests for creating and adding.

pull/3/head
Dustin Oprea 2018-04-19 04:04:19 -04:00
parent f99faad160
commit b5299427bc
3 changed files with 297 additions and 1 deletions

View File

@ -2,6 +2,7 @@ package exif
import (
"errors"
"fmt"
"encoding/binary"
@ -30,6 +31,11 @@ type builderTag struct {
value interface{}
}
func (bt builderTag) String() string {
return fmt.Sprintf("BuilderTag<TAG-ID=(0x%02x) IFD=[%s] VALUE=[%v]>", bt.tagId, bt.ifdName, bt.value)
}
type IfdBuilder struct {
ifdName string
@ -49,7 +55,46 @@ type IfdBuilder struct {
nextIfd *IfdBuilder
}
func (ib *IfdBuilder) String() string {
nextIfdPhrase := ""
if ib.nextIfd != nil {
nextIfdPhrase = ib.nextIfd.ifdName
}
return fmt.Sprintf("IfdBuilder<NAME=[%s] TAG-ID=(0x%02x) BO=[%s] COUNT=(%d) OFFSET=(0x%04x) NEXT-IFD=(0x%04x)>", ib.ifdName, ib.ifdTagId, ib.byteOrder, len(ib.tags), ib.existingOffset, nextIfdPhrase)
}
func (ib *IfdBuilder) Tags() (tags []builderTag) {
return ib.tags
}
func (ib *IfdBuilder) Dump() {
fmt.Printf("IFD: %s\n", ib)
if len(ib.tags) > 0 {
fmt.Printf("\n")
for i, tag := range ib.tags {
fmt.Printf(" (%d): %s\n", i, tag)
}
fmt.Printf("\n")
}
}
func NewIfdBuilder(ifdName string, byteOrder binary.ByteOrder) (ib *IfdBuilder) {
found := false
for _, validName := range validIfds {
if validName == ifdName {
found = true
break
}
}
if found == false {
log.Panicf("ifd not found: [%s]", ifdName)
}
ib = &IfdBuilder{
ifdName: ifdName,
ifdTagId: IfdTagIds[ifdName],
@ -244,6 +289,8 @@ func (ib *IfdBuilder) AddChildIfd(childIfd *IfdBuilder) (err error) {
if childIfd.ifdTagId == 0 {
log.Panicf("IFD [%s] can not be used as a child IFD (not associated with a tag-ID)")
} else if childIfd.byteOrder != ib.byteOrder {
log.Panicf("Child IFD does not have the same byte-order: [%s] != [%s]", childIfd.byteOrder, ib.byteOrder)
}
bt := builderTag{
@ -293,11 +340,16 @@ func (ib *IfdBuilder) AddTagsFromExisting(ifd *Ifd, includeTagIds []uint16, excl
}
if excludeTagIds != nil && len(excludeTagIds) > 0 {
found := false
for _, excludedTagId := range excludeTagIds {
if excludedTagId == tag.TagId {
continue
found = true
}
}
if found == true {
continue
}
}
if includeTagIds != nil && len(includeTagIds) > 0 {

237
ifd_builder_test.go Normal file
View File

@ -0,0 +1,237 @@
package exif
import (
"testing"
"reflect"
"encoding/binary"
"github.com/dsoprea/go-logging"
)
// TODO(dustin): !! We need to have knowledge of the types so that we can validate or induce extra info for the adds.
func TestAdd(t *testing.T) {
ib := NewIfdBuilder(IfdStandard, binary.BigEndian)
bt := builderTag{
tagId: 0x11,
value: "test string",
}
ib.Add(bt)
bt = builderTag{
tagId: 0x22,
value: "test string2",
}
ib.Add(bt)
bt = builderTag{
tagId: 0x33,
value: "test string3",
}
ib.Add(bt)
originalShorts := []uint16 { 0x111, 0x222, 0x333 }
bt = builderTag{
tagId: 0x44,
value: originalShorts,
}
ib.Add(bt)
if ib.ifdName != IfdStandard {
t.Fatalf("IFD name not correct.")
} else if ib.ifdTagId != 0 {
t.Fatalf("IFD tag-ID not correct.")
} else if ib.byteOrder != binary.BigEndian {
t.Fatalf("IFD byte-order not correct.")
} else if len(ib.tags) != 4 {
t.Fatalf("IFD tag-count not correct.")
} else if ib.existingOffset != 0 {
t.Fatalf("IFD offset not correct.")
} else if ib.nextIfd != nil {
t.Fatalf("Next-IFD not correct.")
}
tags := ib.Tags()
if tags[0].tagId != 0x11 {
t.Fatalf("tag (0) tag-ID not correct")
} else if tags[0].value != "test string" {
t.Fatalf("tag (0) value not correct")
}
if tags[1].tagId != 0x22 {
t.Fatalf("tag (1) tag-ID not correct")
} else if tags[1].value != "test string2" {
t.Fatalf("tag (1) value not correct")
}
if tags[2].tagId != 0x33 {
t.Fatalf("tag (2) tag-ID not correct")
} else if tags[2].value != "test string3" {
t.Fatalf("tag (2) value not correct")
}
if tags[3].tagId != 0x44 {
t.Fatalf("tag (3) tag-ID not correct")
} else if reflect.DeepEqual(tags[3].value.([]uint16), originalShorts) != true {
t.Fatalf("tag (3) value not correct")
}
}
func TestSetNextIfd(t *testing.T) {
ib1 := NewIfdBuilder(IfdStandard, binary.BigEndian)
ib2 := NewIfdBuilder(IfdStandard, binary.BigEndian)
if ib1.nextIfd != nil {
t.Fatalf("Next-IFD for IB1 not initially terminal.")
}
err := ib1.SetNextIfd(ib2)
log.PanicIf(err)
if ib1.nextIfd != ib2 {
t.Fatalf("Next-IFD for IB1 not correct.")
} else if ib2.nextIfd != nil {
t.Fatalf("Next-IFD for IB2 terminal.")
}
}
func TestAddChildIfd(t *testing.T) {
ib := NewIfdBuilder(IfdStandard, binary.BigEndian)
bt := builderTag{
tagId: 0x11,
value: "test string",
}
ib.Add(bt)
ibChild := NewIfdBuilder(IfdExif, binary.BigEndian)
err := ib.AddChildIfd(ibChild)
log.PanicIf(err)
bt = builderTag{
tagId: 0x22,
value: "test string",
}
ib.Add(bt)
if ib.tags[0].tagId != 0x11 {
t.Fatalf("first tag not correct")
} else if ib.tags[1].tagId != ibChild.ifdTagId {
t.Fatalf("second tag ID does not match child-IFD tag-ID")
} else if ib.tags[1].value != ibChild {
t.Fatalf("second tagvalue does not match child-IFD")
} else if ib.tags[2].tagId != 0x22 {
t.Fatalf("third tag not correct")
}
}
func TestAddTagsFromExisting(t *testing.T) {
ib := NewIfdBuilder(IfdStandard, binary.BigEndian)
entries := make([]IfdTagEntry, 3)
entries[0] = IfdTagEntry{
TagId: 0x11,
}
entries[1] = IfdTagEntry{
TagId: 0x22,
IfdName: "some ifd",
}
entries[2] = IfdTagEntry{
TagId: 0x33,
}
ifd := &Ifd{
Entries: entries,
}
err := ib.AddTagsFromExisting(ifd, nil, nil)
log.PanicIf(err)
if ib.tags[0].tagId != 0x11 {
t.Fatalf("tag (0) not correct")
} else if ib.tags[1].tagId != 0x33 {
t.Fatalf("tag (1) not correct")
} else if len(ib.tags) != 2 {
t.Fatalf("tag count not correct")
}
}
func TestAddTagsFromExisting__Includes(t *testing.T) {
ib := NewIfdBuilder(IfdStandard, binary.BigEndian)
entries := make([]IfdTagEntry, 3)
entries[0] = IfdTagEntry{
TagId: 0x11,
}
entries[1] = IfdTagEntry{
TagId: 0x22,
IfdName: "some ifd",
}
entries[2] = IfdTagEntry{
TagId: 0x33,
}
ifd := &Ifd{
Entries: entries,
}
err := ib.AddTagsFromExisting(ifd, []uint16 { 0x33 }, nil)
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")
}
}
func TestAddTagsFromExisting__Excludes(t *testing.T) {
ib := NewIfdBuilder(IfdStandard, binary.BigEndian)
entries := make([]IfdTagEntry, 3)
entries[0] = IfdTagEntry{
TagId: 0x11,
}
entries[1] = IfdTagEntry{
TagId: 0x22,
IfdName: "some ifd",
}
entries[2] = IfdTagEntry{
TagId: 0x33,
}
ifd := &Ifd{
Entries: entries,
}
err := ib.AddTagsFromExisting(ifd, nil, []uint16 { 0x11 })
log.PanicIf(err)
if ib.tags[0].tagId != 0x33 {
t.Fatalf("tag not correct")
} else if len(ib.tags) != 1 {
t.Fatalf("tag count not correct")
}
}

View File

@ -20,6 +20,13 @@ const (
var (
tagDataFilepath = ""
validIfds = []string {
IfdStandard,
IfdExif,
IfdGps,
IfdIop,
}
IfdTagIds = map[string]uint16 {
IfdExif: 0x8769,
IfdGps: 0x8825,