aboutsummaryrefslogtreecommitdiff
path: root/tvloader/reader
diff options
context:
space:
mode:
authorRishabhBhatnagar <bhatnagarrishabh4@gmail.com>2020-01-09 20:39:55 +0530
committerRishabhBhatnagar <bhatnagarrishabh4@gmail.com>2020-01-09 21:04:37 +0530
commitcd59ee66408a908f7ef94548814514f6bc9fc906 (patch)
tree550b146d4de0cc00a4784147f7d8f2a7bc93cffe /tvloader/reader
parentf4fef41a45620391fca6481f4700b89de170ab88 (diff)
downloadspdx-tools-cd59ee66408a908f7ef94548814514f6bc9fc906.tar.gz
Create Go Module
- Unpack directory v0 to move all the content to the root directory. - ./v0/* converted to ./* - all the test cases were fixed to remove one directory less indexing for test files - add go.mod - go version 1.13 is used to have a relatively stable versioning system Signed-off-by: RishabhBhatnagar <bhatnagarrishabh4@gmail.com>
Diffstat (limited to 'tvloader/reader')
-rw-r--r--tvloader/reader/reader.go161
-rw-r--r--tvloader/reader/reader_test.go563
2 files changed, 724 insertions, 0 deletions
diff --git a/tvloader/reader/reader.go b/tvloader/reader/reader.go
new file mode 100644
index 0000000..786f7ea
--- /dev/null
+++ b/tvloader/reader/reader.go
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+
+package reader
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "strings"
+ "unicode"
+)
+
+// TagValuePair is a convenience struct for a (tag, value) string pair.
+type TagValuePair struct {
+ Tag string
+ Value string
+}
+
+// ReadTagValues takes an io.Reader, scans it line by line and returns
+// a slice of {string, string} structs in the form {tag, value}.
+func ReadTagValues(content io.Reader) ([]TagValuePair, error) {
+ r := &tvReader{}
+
+ scanner := bufio.NewScanner(content)
+ for scanner.Scan() {
+ // read each line, one by one
+ err := r.readNextLine(scanner.Text())
+ if err != nil {
+ return nil, err
+ }
+ }
+ if err := scanner.Err(); err != nil {
+ return nil, err
+ }
+
+ // finalize and make sure all is well
+ tvList, err := r.finalize()
+ if err != nil {
+ return nil, err
+ }
+
+ // convert internal format to exported TagValueList
+ var exportedTVList []TagValuePair
+ for _, tv := range tvList {
+ tvPair := TagValuePair{Tag: tv.tag, Value: tv.value}
+ exportedTVList = append(exportedTVList, tvPair)
+ }
+
+ return exportedTVList, nil
+}
+
+type tagvalue struct {
+ tag string
+ value string
+}
+
+type tvReader struct {
+ midtext bool
+ tvList []tagvalue
+ currentLine int
+ currentTag string
+ currentValue string
+}
+
+func (reader *tvReader) finalize() ([]tagvalue, error) {
+ if reader.midtext {
+ return nil, fmt.Errorf("finalize called while still midtext parsing a text tag")
+ }
+ return reader.tvList, nil
+}
+
+func (reader *tvReader) readNextLine(line string) error {
+ reader.currentLine++
+
+ if reader.midtext {
+ return reader.readNextLineFromMidtext(line)
+ }
+
+ return reader.readNextLineFromReady(line)
+}
+
+func (reader *tvReader) readNextLineFromReady(line string) error {
+ // strip whitespace from beginning of line
+ line2 := strings.TrimLeftFunc(line, func(r rune) bool {
+ return unicode.IsSpace(r)
+ })
+
+ // ignore empty lines
+ if line2 == "" {
+ return nil
+ }
+
+ // ignore comment lines
+ if strings.HasPrefix(line2, "#") {
+ return nil
+ }
+
+ // split at colon
+ substrings := strings.SplitN(line2, ":", 2)
+ if len(substrings) == 1 {
+ // error if a colon isn't found
+ return fmt.Errorf("no colon found in '%s'", line)
+ }
+
+ // the first substring is the tag
+ reader.currentTag = strings.TrimSpace(substrings[0])
+
+ // determine whether the value contains (or starts) a <text> line
+ substrings = strings.SplitN(substrings[1], "<text>", 2)
+ if len(substrings) == 1 {
+ // no <text> tag found means this is a single-line value
+ // strip whitespace and use as a single line
+ reader.currentValue = strings.TrimSpace(substrings[0])
+ } else {
+ // there was a <text> tag; now decide whether it's multi-line
+ substrings = strings.SplitN(substrings[1], "</text>", 2)
+ if len(substrings) > 1 {
+ // there is also a </text> tag; take the middle part and
+ // set as value
+ reader.currentValue = substrings[0]
+ } else {
+ // there is no </text> tag on this line; switch to midtext
+ reader.currentValue = substrings[0] + "\n"
+ reader.midtext = true
+ return nil
+ }
+ }
+
+ // if we got here, the value was on a single line
+ // so go ahead and add it to the tag-value list
+ tv := tagvalue{reader.currentTag, reader.currentValue}
+ reader.tvList = append(reader.tvList, tv)
+
+ // and reset
+ reader.currentTag = ""
+ reader.currentValue = ""
+
+ return nil
+}
+
+func (reader *tvReader) readNextLineFromMidtext(line string) error {
+ // look for whether the line closes here
+ substrings := strings.SplitN(line, "</text>", 2)
+ if len(substrings) == 1 {
+ // doesn't contain </text>, so keep building the current value
+ reader.currentValue += line + "\n"
+ return nil
+ }
+
+ // contains </text>, so end and record this pair
+ reader.currentValue += substrings[0]
+ tv := tagvalue{reader.currentTag, reader.currentValue}
+ reader.tvList = append(reader.tvList, tv)
+
+ // and reset
+ reader.midtext = false
+ reader.currentTag = ""
+ reader.currentValue = ""
+
+ return nil
+}
diff --git a/tvloader/reader/reader_test.go b/tvloader/reader/reader_test.go
new file mode 100644
index 0000000..73b4c9f
--- /dev/null
+++ b/tvloader/reader/reader_test.go
@@ -0,0 +1,563 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+package reader
+
+import (
+ "strings"
+ "testing"
+)
+
+func TestCanReadTagValues(t *testing.T) {
+ sText := `
+Tag1: Value1
+Tag2: Value2
+
+Tag3: <text>line 1
+ line 2</text>
+# Comment
+Tag4: Value4
+Tag5: Value 5
+`
+ sReader := strings.NewReader(sText)
+
+ tvPairList, err := ReadTagValues(sReader)
+ if err != nil {
+ t.Errorf("got error when calling ReadTagValues: %v", err)
+ }
+ if len(tvPairList) != 5 {
+ t.Fatalf("expected len(tvPairList) to be 5, got %d", len(tvPairList))
+ }
+ if tvPairList[0].Tag != "Tag1" {
+ t.Errorf("expected tvPairList[0].Tag to be Tag1, got %s", tvPairList[0].Tag)
+ }
+ if tvPairList[0].Value != "Value1" {
+ t.Errorf("expected tvPairList[0].Value to be Value1, got %s", tvPairList[0].Value)
+ }
+ if tvPairList[1].Tag != "Tag2" {
+ t.Errorf("expected tvPairList[1].Tag to be Tag2, got %s", tvPairList[1].Tag)
+ }
+ if tvPairList[1].Value != "Value2" {
+ t.Errorf("expected tvPairList[1].Value to be Value2, got %s", tvPairList[1].Value)
+ }
+ if tvPairList[2].Tag != "Tag3" {
+ t.Errorf("expected tvPairList[2].Tag to be Tag3, got %s", tvPairList[2].Tag)
+ }
+ if tvPairList[2].Value != "line 1\n line 2" {
+ t.Errorf("expected tvPairList[2].Value to be line 1\n line 2, got %s", tvPairList[2].Value)
+ }
+ if tvPairList[3].Tag != "Tag4" {
+ t.Errorf("expected tvPairList[3].Tag to be Tag4, got %s", tvPairList[3].Tag)
+ }
+ if tvPairList[3].Value != "Value4" {
+ t.Errorf("expected tvPairList[3].Value to be Value4, got %s", tvPairList[3].Value)
+ }
+ if tvPairList[4].Tag != "Tag5" {
+ t.Errorf("expected tvPairList[4].Tag to be Tag5, got %s", tvPairList[4].Tag)
+ }
+ if tvPairList[4].Value != "Value 5" {
+ t.Errorf("expected tvPairList[4].Value to be Value 5, got %s", tvPairList[4].Value)
+ }
+}
+
+func TestCanGetTVListWithFinalize(t *testing.T) {
+ reader := &tvReader{}
+ err := reader.readNextLine("Tag:value")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+ tvList, err := reader.finalize()
+ if err != nil {
+ t.Errorf("got error when calling finalize: %v", err)
+ }
+ if len(tvList) != 1 || tvList[0].tag != "Tag" || tvList[0].value != "value" {
+ t.Errorf("got invalid tag/value list: %v", tvList)
+ }
+}
+
+func TestCanGetTVListIncludingMultilineWithFinalize(t *testing.T) {
+ reader := &tvReader{}
+ err := reader.readNextLine("Tag:<text>value")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+ err = reader.readNextLine("rest of value</text>")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+ tvList, err := reader.finalize()
+ if err != nil {
+ t.Errorf("got error when calling finalize: %v", err)
+ }
+ if len(tvList) != 1 || tvList[0].tag != "Tag" || tvList[0].value != "value\nrest of value" {
+ t.Errorf("got invalid tag/value list: %v", tvList)
+ }
+}
+
+func TestCannotFinalizeIfInMidtextState(t *testing.T) {
+ reader := &tvReader{}
+ err := reader.readNextLine("Tag:<text>value")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+ _, err = reader.finalize()
+ if err == nil {
+ t.Errorf("should have gotten error when calling finalize midtext")
+ }
+}
+
+func TestCurrentLineIncreasesOnEachReadCall(t *testing.T) {
+ reader := &tvReader{}
+ err := reader.readNextLine("Tag:value")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+ if reader.currentLine != 1 {
+ t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
+ }
+
+ reader.currentLine = 23
+ err = reader.readNextLine("Tag:value")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+ if reader.currentLine != 24 {
+ t.Errorf("expected %d for currentLine, got %d", 23, reader.currentLine)
+ }
+}
+
+func TestReadyCanReadSingleTagValue(t *testing.T) {
+ reader := &tvReader{}
+ err := reader.readNextLine("Tag:value")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+ if len(reader.tvList) != 1 || reader.tvList[0].tag != "Tag" || reader.tvList[0].value != "value" {
+ t.Errorf("got invalid tag/value list: %v", reader.tvList)
+ }
+ if reader.currentLine != 1 {
+ t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
+ }
+ if reader.currentTag != "" {
+ t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
+ }
+ if reader.currentValue != "" {
+ t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
+ }
+}
+
+func TestReadyCanStripWhitespaceFromValue(t *testing.T) {
+ reader := &tvReader{}
+ err := reader.readNextLine("Tag: value ")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+ if len(reader.tvList) != 1 || reader.tvList[0].tag != "Tag" || reader.tvList[0].value != "value" {
+ t.Errorf("got invalid tag/value list: %v", reader.tvList)
+ }
+}
+
+func TestReadyCannotReadLineWithNoColon(t *testing.T) {
+ reader := &tvReader{}
+ err := reader.readNextLine("No colon should be an error")
+ if err == nil {
+ t.Errorf("should have gotten error when calling readNextLine")
+ }
+}
+
+func TestReadyTextTagSwitchesToMidtext(t *testing.T) {
+ reader := &tvReader{}
+ err := reader.readNextLine("Tag: <text>This begins a multiline value")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+ if len(reader.tvList) != 0 {
+ t.Errorf("expected empty tag/value list, got %v", reader.tvList)
+ }
+ if !reader.midtext {
+ t.Errorf("expected midtext to be true, got false")
+ }
+ if reader.currentLine != 1 {
+ t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
+ }
+ if reader.currentTag != "Tag" {
+ t.Errorf("expected %s for currentTag, got %s", "Tag", reader.currentTag)
+ }
+ if reader.currentValue != "This begins a multiline value\n" {
+ t.Errorf("expected %s for currentValue, got %s", "This begins a multiline value\n", reader.currentValue)
+ }
+}
+
+func TestReadyTextTagAndClosingTagInOneLineFinishesRead(t *testing.T) {
+ reader := &tvReader{}
+ err := reader.readNextLine("Tag: <text>Just one line</text>")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+ if len(reader.tvList) != 1 || reader.tvList[0].tag != "Tag" || reader.tvList[0].value != "Just one line" {
+ t.Errorf("got invalid tag/value list: %v", reader.tvList)
+ }
+ if reader.midtext {
+ t.Errorf("expected midtext to be false, got true")
+ }
+ if reader.currentLine != 1 {
+ t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
+ }
+ if reader.currentTag != "" {
+ t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
+ }
+ if reader.currentValue != "" {
+ t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
+ }
+}
+
+func TestCanReadMultilineTextAcrossThreeLines(t *testing.T) {
+ reader := &tvReader{}
+ err := reader.readNextLine("Tag: <text>This value")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+ err = reader.readNextLine("is three")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+ err = reader.readNextLine("lines long</text>")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+
+ if len(reader.tvList) != 1 || reader.tvList[0].tag != "Tag" || reader.tvList[0].value != "This value\nis three\nlines long" {
+ t.Errorf("got invalid tag/value list: %v", reader.tvList)
+ }
+ if reader.midtext {
+ t.Errorf("expected midtext to be false, got true")
+ }
+ if reader.currentLine != 3 {
+ t.Errorf("expected %d for currentLine, got %d", 3, reader.currentLine)
+ }
+ if reader.currentTag != "" {
+ t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
+ }
+ if reader.currentValue != "" {
+ t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
+ }
+}
+
+func TestMidtextContinuesIfNoClosingText(t *testing.T) {
+ reader := &tvReader{}
+ reader.midtext = true
+ reader.currentLine = 1
+ reader.currentTag = "Multiline"
+ reader.currentValue = "First line\n"
+
+ err := reader.readNextLine("Second line")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+
+ if len(reader.tvList) != 0 {
+ t.Errorf("expected empty tag/value list, got %v", reader.tvList)
+ }
+ if !reader.midtext {
+ t.Errorf("expected midtext to be true, got false")
+ }
+ if reader.currentLine != 2 {
+ t.Errorf("expected %d for currentLine, got %d", 2, reader.currentLine)
+ }
+ if reader.currentTag != "Multiline" {
+ t.Errorf("expected %s for currentTag, got %s", "Multiline", reader.currentTag)
+ }
+ if reader.currentValue != "First line\nSecond line\n" {
+ t.Errorf("expected %s for currentValue, got %s", "First line\nSecond line\n", reader.currentValue)
+ }
+}
+
+func TestMidtextFinishesIfReachingClosingText(t *testing.T) {
+ reader := &tvReader{}
+ reader.midtext = true
+ reader.currentLine = 1
+ reader.currentTag = "Multiline"
+ reader.currentValue = "First line\n"
+
+ err := reader.readNextLine("Second line</text>")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+
+ if len(reader.tvList) != 1 || reader.tvList[0].tag != "Multiline" || reader.tvList[0].value != "First line\nSecond line" {
+ t.Errorf("got invalid tag/value list: %v", reader.tvList)
+ }
+ if reader.midtext {
+ t.Errorf("expected midtext to be false, got true")
+ }
+ if reader.currentLine != 2 {
+ t.Errorf("expected %d for currentLine, got %d", 2, reader.currentLine)
+ }
+ if reader.currentTag != "" {
+ t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
+ }
+ if reader.currentValue != "" {
+ t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
+ }
+}
+
+func TestReadyIgnoresCommentLines(t *testing.T) {
+ reader := &tvReader{}
+ err := reader.readNextLine("# this is a comment")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+
+ if len(reader.tvList) != 0 {
+ t.Errorf("expected empty tag/value list, got %v", reader.tvList)
+ }
+ if reader.midtext {
+ t.Errorf("expected midtext to be false, got true")
+ }
+ if reader.currentLine != 1 {
+ t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
+ }
+ if reader.currentTag != "" {
+ t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
+ }
+ if reader.currentValue != "" {
+ t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
+ }
+}
+
+func TestMidtextIncludesCommentLines(t *testing.T) {
+ reader := &tvReader{}
+ reader.midtext = true
+ reader.currentLine = 1
+ reader.currentTag = "Multiline"
+ reader.currentValue = "First line\n"
+
+ err := reader.readNextLine("# This is part of multiline text")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+
+ if len(reader.tvList) != 0 {
+ t.Errorf("expected empty tag/value list, got %v", reader.tvList)
+ }
+ if !reader.midtext {
+ t.Errorf("expected midtext to be true, got false")
+ }
+ if reader.currentLine != 2 {
+ t.Errorf("expected %d for currentLine, got %d", 2, reader.currentLine)
+ }
+ if reader.currentTag != "Multiline" {
+ t.Errorf("expected %s for currentTag, got %s", "Multiline", reader.currentTag)
+ }
+ if reader.currentValue != "First line\n# This is part of multiline text\n" {
+ t.Errorf("expected %s for currentValue, got %s", "First line\n# This is part of multiline text\n", reader.currentValue)
+ }
+}
+
+func TestReadyIgnoresEmptyLines(t *testing.T) {
+ reader := &tvReader{}
+ err := reader.readNextLine("")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+
+ if len(reader.tvList) != 0 {
+ t.Errorf("expected empty tag/value list, got %v", reader.tvList)
+ }
+ if reader.midtext {
+ t.Errorf("expected midtext to be false, got true")
+ }
+ if reader.currentLine != 1 {
+ t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
+ }
+ if reader.currentTag != "" {
+ t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
+ }
+ if reader.currentValue != "" {
+ t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
+ }
+}
+
+func TestMidtextIncludesEmptyLines(t *testing.T) {
+ reader := &tvReader{}
+ reader.midtext = true
+ reader.currentLine = 1
+ reader.currentTag = "Multiline"
+ reader.currentValue = "First line\n"
+
+ err := reader.readNextLine("")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+
+ if len(reader.tvList) != 0 {
+ t.Errorf("expected empty tag/value list, got %v", reader.tvList)
+ }
+ if !reader.midtext {
+ t.Errorf("expected midtext to be true, got false")
+ }
+ if reader.currentLine != 2 {
+ t.Errorf("expected %d for currentLine, got %d", 2, reader.currentLine)
+ }
+ if reader.currentTag != "Multiline" {
+ t.Errorf("expected %s for currentTag, got %s", "Multiline", reader.currentTag)
+ }
+ if reader.currentValue != "First line\n\n" {
+ t.Errorf("expected %s for currentValue, got %s", "First line\n\n", reader.currentValue)
+ }
+}
+
+func TestReadyIgnoresWhitespaceOnlyLines(t *testing.T) {
+ reader := &tvReader{}
+ err := reader.readNextLine(" \t\t\t ")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+
+ if len(reader.tvList) != 0 {
+ t.Errorf("expected empty tag/value list, got %v", reader.tvList)
+ }
+ if reader.midtext {
+ t.Errorf("expected midtext to be false, got true")
+ }
+ if reader.currentLine != 1 {
+ t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
+ }
+ if reader.currentTag != "" {
+ t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
+ }
+ if reader.currentValue != "" {
+ t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
+ }
+}
+
+func TestMidtextIncludesWhitespaceOnlyLines(t *testing.T) {
+ reader := &tvReader{}
+ reader.midtext = true
+ reader.currentLine = 1
+ reader.currentTag = "Multiline"
+ reader.currentValue = "First line\n"
+
+ err := reader.readNextLine(" \t\t ")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+
+ if len(reader.tvList) != 0 {
+ t.Errorf("expected empty tag/value list, got %v", reader.tvList)
+ }
+ if !reader.midtext {
+ t.Errorf("expected midtext to be true, got false")
+ }
+ if reader.currentLine != 2 {
+ t.Errorf("expected %d for currentLine, got %d", 2, reader.currentLine)
+ }
+ if reader.currentTag != "Multiline" {
+ t.Errorf("expected %s for currentTag, got %s", "Multiline", reader.currentTag)
+ }
+ if reader.currentValue != "First line\n \t\t \n" {
+ t.Errorf("expected %s for currentValue, got %s", "First line\n \t\t \n", reader.currentValue)
+ }
+}
+
+func TestReadyIgnoresSpacesBeforeTag(t *testing.T) {
+ reader := &tvReader{}
+ err := reader.readNextLine(" \t Tag:value")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+ if len(reader.tvList) != 1 || reader.tvList[0].tag != "Tag" || reader.tvList[0].value != "value" {
+ t.Errorf("got invalid tag/value list: %v", reader.tvList)
+ }
+ if reader.currentLine != 1 {
+ t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
+ }
+ if reader.currentTag != "" {
+ t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
+ }
+ if reader.currentValue != "" {
+ t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
+ }
+}
+
+func TestReadyIgnoresSpacesBeforeCommentLines(t *testing.T) {
+ reader := &tvReader{}
+ err := reader.readNextLine(" \t\t # this is a comment")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+
+ if len(reader.tvList) != 0 {
+ t.Errorf("expected empty tag/value list, got %v", reader.tvList)
+ }
+ if reader.midtext {
+ t.Errorf("expected midtext to be false, got true")
+ }
+ if reader.currentLine != 1 {
+ t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
+ }
+ if reader.currentTag != "" {
+ t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
+ }
+ if reader.currentValue != "" {
+ t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
+ }
+}
+
+func TestReadyIgnoresSpacesBetweenTagAndColon(t *testing.T) {
+ reader := &tvReader{}
+ err := reader.readNextLine("Tag \t :value")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+ if len(reader.tvList) != 1 || reader.tvList[0].tag != "Tag" || reader.tvList[0].value != "value" {
+ t.Errorf("got invalid tag/value list: %v", reader.tvList)
+ }
+ if reader.currentLine != 1 {
+ t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
+ }
+ if reader.currentTag != "" {
+ t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
+ }
+ if reader.currentValue != "" {
+ t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
+ }
+}
+
+func TestReadyIgnoresSpacesBetweenColonAndValue(t *testing.T) {
+ reader := &tvReader{}
+ err := reader.readNextLine("Tag: \t value")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+ if len(reader.tvList) != 1 || reader.tvList[0].tag != "Tag" || reader.tvList[0].value != "value" {
+ t.Errorf("got invalid tag/value list: %v", reader.tvList)
+ }
+ if reader.currentLine != 1 {
+ t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
+ }
+ if reader.currentTag != "" {
+ t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
+ }
+ if reader.currentValue != "" {
+ t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
+ }
+}
+
+func TestReadyIgnoresSpacesAfterEndOfValue(t *testing.T) {
+ reader := &tvReader{}
+ err := reader.readNextLine("Tag:value \t ")
+ if err != nil {
+ t.Errorf("got error when calling readNextLine: %v", err)
+ }
+ if len(reader.tvList) != 1 || reader.tvList[0].tag != "Tag" || reader.tvList[0].value != "value" {
+ t.Errorf("got invalid tag/value list: %v", reader.tvList)
+ }
+ if reader.currentLine != 1 {
+ t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
+ }
+ if reader.currentTag != "" {
+ t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
+ }
+ if reader.currentValue != "" {
+ t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
+ }
+}