From f9267550eb244e4bd6d7b5b3c2b2f517148edb6c Mon Sep 17 00:00:00 2001 From: Dustin Oprea Date: Fri, 20 Apr 2018 04:16:48 -0400 Subject: [PATCH] ifd_builder: Added renaming tests. --- ifd_builder.go | 70 ++-- ifd_builder_test.go | 772 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 808 insertions(+), 34 deletions(-) diff --git a/ifd_builder.go b/ifd_builder.go index c0c95f1..53313a3 100644 --- a/ifd_builder.go +++ b/ifd_builder.go @@ -171,7 +171,7 @@ func (ib *IfdBuilder) DeleteFirst(tagId uint16) (err error) { return nil } -func (ib *IfdBuilder) DeleteAll(tagId uint16) (err error) { +func (ib *IfdBuilder) DeleteAll(tagId uint16) (n int, err error) { defer func() { if state := recover(); state != nil { err = log.Wrap(state.(error)) @@ -185,8 +185,43 @@ func (ib *IfdBuilder) DeleteAll(tagId uint16) (err error) { } else if err != nil { log.Panic(err) } + + n++ } + return n, nil +} + +func (ib *IfdBuilder) ReplaceAt(position int, bt builderTag) (err error) { + defer func() { + if state := recover(); state != nil { + err = log.Wrap(state.(error)) + } + }() + + if position < 0 { + log.Panicf("replacement position must be 0 or greater") + } else if position >= len(ib.tags) { + log.Panicf("replacement position does not exist") + } + + ib.tags[position] = bt + + return nil +} + +func (ib *IfdBuilder) Replace(tagId uint16, bt builderTag) (err error) { + defer func() { + if state := recover(); state != nil { + err = log.Wrap(state.(error)) + } + }() + + position, err := ib.Find(tagId) + log.PanicIf(err) + + ib.tags[position] = bt + return nil } @@ -228,39 +263,6 @@ func (ib *IfdBuilder) Find(tagId uint16) (position int, err error) { return found[0], nil } -func (ib *IfdBuilder) ReplaceAt(position int, bt builderTag) (err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - if position < 0 { - log.Panicf("replacement position must be 0 or greater") - } else if position >= len(ib.tags) { - log.Panicf("replacement position does not exist") - } - - ib.tags[position] = bt - - return nil -} - -func (ib *IfdBuilder) Replace(tagId uint16, bt builderTag) (err error) { - defer func() { - if state := recover(); state != nil { - err = log.Wrap(state.(error)) - } - }() - - position, err := ib.Find(tagId) - log.PanicIf(err) - - ib.tags[position] = bt - - return nil -} - // TODO(dustin): !! Switch to producing bytes immediately so that they're validated. func (ib *IfdBuilder) Add(bt builderTag) (err error) { diff --git a/ifd_builder_test.go b/ifd_builder_test.go index a49077d..925e1d1 100644 --- a/ifd_builder_test.go +++ b/ifd_builder_test.go @@ -235,3 +235,775 @@ func TestAddTagsFromExisting__Excludes(t *testing.T) { t.Fatalf("tag count not correct") } } + +func TestFindN_First_1(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) + + found, err := ib.FindN(0x11, 1) + log.PanicIf(err) + + if len(found) != 1 { + log.Panicf("Exactly one result was not found: (%d)", len(found)) + } else if found[0] != 0 { + log.Panicf("Result was not in the right place: (%d)", found[0]) + } + + tags := ib.Tags() + bt = tags[found[0]] + + if bt.tagId != 0x11 { + log.Panicf("Found entry is not correct: (0x%02x)", bt.tagId) + } +} + +func TestFindN_First_2_1Returned(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) + + found, err := ib.FindN(0x11, 2) + log.PanicIf(err) + + if len(found) != 1 { + log.Panicf("Exactly one result was not found: (%d)", len(found)) + } else if found[0] != 0 { + log.Panicf("Result was not in the right place: (%d)", found[0]) + } + + tags := ib.Tags() + bt = tags[found[0]] + + if bt.tagId != 0x11 { + log.Panicf("Found entry is not correct: (0x%02x)", bt.tagId) + } +} + +func TestFindN_First_2_2Returned(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) + + bt = builderTag{ + tagId: 0x11, + value: "test string4", + } + + ib.Add(bt) + + bt = builderTag{ + tagId: 0x11, + value: "test string5", + } + + ib.Add(bt) + + found, err := ib.FindN(0x11, 2) + log.PanicIf(err) + + if len(found) != 2 { + log.Panicf("Exactly one result was not found: (%d)", len(found)) + } else if found[0] != 0 { + log.Panicf("First result was not in the right place: (%d)", found[0]) + } else if found[1] != 3 { + log.Panicf("Second result was not in the right place: (%d)", found[1]) + } + + tags := ib.Tags() + + bt = tags[found[0]] + if bt.tagId != 0x11 || bt.value != "test string" { + log.Panicf("Found entry 0 is not correct: (0x%02x) [%s]", bt.tagId, bt.value) + } + + bt = tags[found[1]] + if bt.tagId != 0x11 || bt.value != "test string4" { + log.Panicf("Found entry 1 is not correct: (0x%02x) [%s]", bt.tagId, bt.value) + } +} + +func TestFindN_Middle_WithDuplicates(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) + + bt = builderTag{ + tagId: 0x11, + value: "test string4", + } + + ib.Add(bt) + + bt = builderTag{ + tagId: 0x11, + value: "test string5", + } + + ib.Add(bt) + + bt = builderTag{ + tagId: 0x33, + value: "test string6", + } + + ib.Add(bt) + + found, err := ib.FindN(0x33, 1) + log.PanicIf(err) + + if len(found) != 1 { + log.Panicf("Exactly one result was not found: (%d)", len(found)) + } else if found[0] != 2 { + log.Panicf("Result was not in the right place: (%d)", found[0]) + } + + tags := ib.Tags() + bt = tags[found[0]] + + if bt.tagId != 0x33 { + log.Panicf("Found entry is not correct: (0x%02x)", bt.tagId) + } +} + +func TestFindN_Middle_NoDuplicates(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) + + bt = builderTag{ + tagId: 0x11, + value: "test string4", + } + + ib.Add(bt) + + found, err := ib.FindN(0x33, 1) + log.PanicIf(err) + + if len(found) != 1 { + log.Panicf("Exactly one result was not found: (%d)", len(found)) + } else if found[0] != 2 { + log.Panicf("Result was not in the right place: (%d)", found[0]) + } + + tags := ib.Tags() + bt = tags[found[0]] + + if bt.tagId != 0x33 { + log.Panicf("Found entry is not correct: (0x%02x)", bt.tagId) + } +} + +func TestFindN_Miss(t *testing.T) { + ib := NewIfdBuilder(IfdStandard, binary.BigEndian) + + found, err := ib.FindN(0x11, 1) + log.PanicIf(err) + + if len(found) != 0 { + t.Fatalf("Expected empty results.") + } +} + +func TestFind_Hit(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) + + bt = builderTag{ + tagId: 0x11, + value: "test string4", + } + + ib.Add(bt) + + position, err := ib.Find(0x33) + log.PanicIf(err) + + if position != 2 { + log.Panicf("Result was not in the right place: (%d)", position) + } + + tags := ib.Tags() + bt = tags[position] + + if bt.tagId != 0x33 { + log.Panicf("Found entry is not correct: (0x%02x)", bt.tagId) + } +} + +func TestFind_Miss(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) + + bt = builderTag{ + tagId: 0x11, + value: "test string4", + } + + ib.Add(bt) + + _, err := ib.Find(0x99) + if err == nil { + t.Fatalf("Expected an error.") + } else if log.Is(err, ErrTagEntryNotFound) == false { + log.Panic(err) + } +} + +func TestReplace(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) + + currentIds := make([]uint16, 3) + for i, bt := range ib.Tags() { + currentIds[i] = bt.tagId + } + + if reflect.DeepEqual([]uint16 { 0x11, 0x22, 0x33 }, currentIds) == false { + t.Fatalf("Pre-replace tags are not correct.") + } + + bt = builderTag{ + tagId: 0x99, + value: "test string4", + } + + err := ib.Replace(0x22, bt) + log.PanicIf(err) + + currentIds = make([]uint16, 3) + for i, bt := range ib.Tags() { + currentIds[i] = bt.tagId + } + + if reflect.DeepEqual([]uint16 { 0x11, 0x99, 0x33 }, currentIds) == false { + t.Fatalf("Post-replace tags are not correct.") + } +} + +func TestReplaceN(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) + + currentIds := make([]uint16, 3) + for i, bt := range ib.Tags() { + currentIds[i] = bt.tagId + } + + if reflect.DeepEqual([]uint16 { 0x11, 0x22, 0x33 }, currentIds) == false { + t.Fatalf("Pre-replace tags are not correct.") + } + + bt = builderTag{ + tagId: 0xA9, + value: "test string4", + } + + err := ib.ReplaceAt(1, bt) + log.PanicIf(err) + + currentIds = make([]uint16, 3) + for i, bt := range ib.Tags() { + currentIds[i] = bt.tagId + } + + if reflect.DeepEqual([]uint16 { 0x11, 0xA9, 0x33 }, currentIds) == false { + t.Fatalf("Post-replace tags are not correct.") + } +} + +func TestDeleteFirst(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: 0x22, + value: "test string3", + } + + ib.Add(bt) + + bt = builderTag{ + tagId: 0x33, + value: "test string4", + } + + ib.Add(bt) + + + if len(ib.Tags()) != 4 { + t.Fatalf("Pre-delete tag count not correct.") + } + + currentIds := make([]uint16, 4) + for i, bt := range ib.Tags() { + currentIds[i] = bt.tagId + } + + if reflect.DeepEqual([]uint16 { 0x11, 0x22, 0x22, 0x33 }, currentIds) == false { + t.Fatalf("Pre-delete tags not correct.") + } + + + err := ib.DeleteFirst(0x22) + log.PanicIf(err) + + if len(ib.Tags()) != 3 { + t.Fatalf("Post-delete (1) tag count not correct.") + } + + currentIds = make([]uint16, 3) + for i, bt := range ib.Tags() { + currentIds[i] = bt.tagId + } + + if reflect.DeepEqual([]uint16 { 0x11, 0x22, 0x33 }, currentIds) == false { + t.Fatalf("Post-delete (1) tags not correct.") + } + + + err = ib.DeleteFirst(0x22) + log.PanicIf(err) + + if len(ib.Tags()) != 2 { + t.Fatalf("Post-delete (2) tag count not correct.") + } + + currentIds = make([]uint16, 2) + for i, bt := range ib.Tags() { + currentIds[i] = bt.tagId + } + + if reflect.DeepEqual([]uint16 { 0x11, 0x33 }, currentIds) == false { + t.Fatalf("Post-delete (2) tags not correct.") + } + + + err = ib.DeleteFirst(0x22) + if err == nil { + t.Fatalf("Expected an error.") + } else if log.Is(err, ErrTagEntryNotFound) == false { + log.Panic(err) + } +} + +func TestDeleteN(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: 0x22, + value: "test string3", + } + + ib.Add(bt) + + bt = builderTag{ + tagId: 0x33, + value: "test string4", + } + + ib.Add(bt) + + + if len(ib.Tags()) != 4 { + t.Fatalf("Pre-delete tag count not correct.") + } + + currentIds := make([]uint16, 4) + for i, bt := range ib.Tags() { + currentIds[i] = bt.tagId + } + + if reflect.DeepEqual([]uint16 { 0x11, 0x22, 0x22, 0x33 }, currentIds) == false { + t.Fatalf("Pre-delete tags not correct.") + } + + + err := ib.DeleteN(0x22, 1) + log.PanicIf(err) + + if len(ib.Tags()) != 3 { + t.Fatalf("Post-delete (1) tag count not correct.") + } + + currentIds = make([]uint16, 3) + for i, bt := range ib.Tags() { + currentIds[i] = bt.tagId + } + + if reflect.DeepEqual([]uint16 { 0x11, 0x22, 0x33 }, currentIds) == false { + t.Fatalf("Post-delete (1) tags not correct.") + } + + + err = ib.DeleteN(0x22, 1) + log.PanicIf(err) + + if len(ib.Tags()) != 2 { + t.Fatalf("Post-delete (2) tag count not correct.") + } + + currentIds = make([]uint16, 2) + for i, bt := range ib.Tags() { + currentIds[i] = bt.tagId + } + + if reflect.DeepEqual([]uint16 { 0x11, 0x33 }, currentIds) == false { + t.Fatalf("Post-delete (2) tags not correct.") + } + + + err = ib.DeleteN(0x22, 1) + if err == nil { + t.Fatalf("Expected an error.") + } else if log.Is(err, ErrTagEntryNotFound) == false { + log.Panic(err) + } +} + +func TestDeleteN_Two(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: 0x22, + value: "test string3", + } + + ib.Add(bt) + + bt = builderTag{ + tagId: 0x33, + value: "test string4", + } + + ib.Add(bt) + + + if len(ib.Tags()) != 4 { + t.Fatalf("Pre-delete tag count not correct.") + } + + currentIds := make([]uint16, 4) + for i, bt := range ib.Tags() { + currentIds[i] = bt.tagId + } + + if reflect.DeepEqual([]uint16 { 0x11, 0x22, 0x22, 0x33 }, currentIds) == false { + t.Fatalf("Pre-delete tags not correct.") + } + + + err := ib.DeleteN(0x22, 2) + log.PanicIf(err) + + if len(ib.Tags()) != 2 { + t.Fatalf("Post-delete tag count not correct.") + } + + currentIds = make([]uint16, 2) + for i, bt := range ib.Tags() { + currentIds[i] = bt.tagId + } + + if reflect.DeepEqual([]uint16 { 0x11, 0x33 }, currentIds) == false { + t.Fatalf("Post-delete tags not correct.") + } + + + err = ib.DeleteFirst(0x22) + if err == nil { + t.Fatalf("Expected an error.") + } else if log.Is(err, ErrTagEntryNotFound) == false { + log.Panic(err) + } +} + +func TestDeleteAll(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: 0x22, + value: "test string3", + } + + ib.Add(bt) + + bt = builderTag{ + tagId: 0x33, + value: "test string4", + } + + ib.Add(bt) + + + if len(ib.Tags()) != 4 { + t.Fatalf("Pre-delete tag count not correct.") + } + + currentIds := make([]uint16, 4) + for i, bt := range ib.Tags() { + currentIds[i] = bt.tagId + } + + if reflect.DeepEqual([]uint16 { 0x11, 0x22, 0x22, 0x33 }, currentIds) == false { + t.Fatalf("Pre-delete tags not correct.") + } + + + n, err := ib.DeleteAll(0x22) + log.PanicIf(err) + + if n != 2 { + t.Fatalf("Returned delete tag count not correct.") + } else if len(ib.Tags()) != 2 { + t.Fatalf("Post-delete tag count not correct.") + } + + currentIds = make([]uint16, 2) + for i, bt := range ib.Tags() { + currentIds[i] = bt.tagId + } + + if reflect.DeepEqual([]uint16 { 0x11, 0x33 }, currentIds) == false { + t.Fatalf("Post-delete tags not correct.") + } + + + err = ib.DeleteFirst(0x22) + if err == nil { + t.Fatalf("Expected an error.") + } else if log.Is(err, ErrTagEntryNotFound) == false { + log.Panic(err) + } +}