xref: /aosp_15_r20/external/spdx-tools/tvloader/reader/reader_test.go (revision ba677afa8f67bb56cbc794f4d0e378e0da058e16)
1// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2package reader
3
4import (
5	"strings"
6	"testing"
7)
8
9func TestCanReadTagValues(t *testing.T) {
10	sText := `
11Tag1: Value1
12Tag2:    Value2
13
14Tag3: <text>line 1
15   line 2</text>
16# Comment
17Tag4: Value4
18Tag5: Value 5
19`
20	sReader := strings.NewReader(sText)
21
22	tvPairList, err := ReadTagValues(sReader)
23	if err != nil {
24		t.Errorf("got error when calling ReadTagValues: %v", err)
25	}
26	if len(tvPairList) != 5 {
27		t.Fatalf("expected len(tvPairList) to be 5, got %d", len(tvPairList))
28	}
29	if tvPairList[0].Tag != "Tag1" {
30		t.Errorf("expected tvPairList[0].Tag to be Tag1, got %s", tvPairList[0].Tag)
31	}
32	if tvPairList[0].Value != "Value1" {
33		t.Errorf("expected tvPairList[0].Value to be Value1, got %s", tvPairList[0].Value)
34	}
35	if tvPairList[1].Tag != "Tag2" {
36		t.Errorf("expected tvPairList[1].Tag to be Tag2, got %s", tvPairList[1].Tag)
37	}
38	if tvPairList[1].Value != "Value2" {
39		t.Errorf("expected tvPairList[1].Value to be Value2, got %s", tvPairList[1].Value)
40	}
41	if tvPairList[2].Tag != "Tag3" {
42		t.Errorf("expected tvPairList[2].Tag to be Tag3, got %s", tvPairList[2].Tag)
43	}
44	if tvPairList[2].Value != "line 1\n   line 2" {
45		t.Errorf("expected tvPairList[2].Value to be line 1\n   line 2, got %s", tvPairList[2].Value)
46	}
47	if tvPairList[3].Tag != "Tag4" {
48		t.Errorf("expected tvPairList[3].Tag to be Tag4, got %s", tvPairList[3].Tag)
49	}
50	if tvPairList[3].Value != "Value4" {
51		t.Errorf("expected tvPairList[3].Value to be Value4, got %s", tvPairList[3].Value)
52	}
53	if tvPairList[4].Tag != "Tag5" {
54		t.Errorf("expected tvPairList[4].Tag to be Tag5, got %s", tvPairList[4].Tag)
55	}
56	if tvPairList[4].Value != "Value 5" {
57		t.Errorf("expected tvPairList[4].Value to be Value 5, got %s", tvPairList[4].Value)
58	}
59}
60
61func TestCanGetTVListWithFinalize(t *testing.T) {
62	reader := &tvReader{}
63	err := reader.readNextLine("Tag:value")
64	if err != nil {
65		t.Errorf("got error when calling readNextLine: %v", err)
66	}
67	tvList, err := reader.finalize()
68	if err != nil {
69		t.Errorf("got error when calling finalize: %v", err)
70	}
71	if len(tvList) != 1 || tvList[0].tag != "Tag" || tvList[0].value != "value" {
72		t.Errorf("got invalid tag/value list: %v", tvList)
73	}
74}
75
76func TestCanGetTVListIncludingMultilineWithFinalize(t *testing.T) {
77	reader := &tvReader{}
78	err := reader.readNextLine("Tag:<text>value")
79	if err != nil {
80		t.Errorf("got error when calling readNextLine: %v", err)
81	}
82	err = reader.readNextLine("rest of value</text>")
83	if err != nil {
84		t.Errorf("got error when calling readNextLine: %v", err)
85	}
86	tvList, err := reader.finalize()
87	if err != nil {
88		t.Errorf("got error when calling finalize: %v", err)
89	}
90	if len(tvList) != 1 || tvList[0].tag != "Tag" || tvList[0].value != "value\nrest of value" {
91		t.Errorf("got invalid tag/value list: %v", tvList)
92	}
93}
94
95func TestCannotFinalizeIfInMidtextState(t *testing.T) {
96	reader := &tvReader{}
97	err := reader.readNextLine("Tag:<text>value")
98	if err != nil {
99		t.Errorf("got error when calling readNextLine: %v", err)
100	}
101	_, err = reader.finalize()
102	if err == nil {
103		t.Errorf("should have gotten error when calling finalize midtext")
104	}
105}
106
107func TestCurrentLineIncreasesOnEachReadCall(t *testing.T) {
108	reader := &tvReader{}
109	err := reader.readNextLine("Tag:value")
110	if err != nil {
111		t.Errorf("got error when calling readNextLine: %v", err)
112	}
113	if reader.currentLine != 1 {
114		t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
115	}
116
117	reader.currentLine = 23
118	err = reader.readNextLine("Tag:value")
119	if err != nil {
120		t.Errorf("got error when calling readNextLine: %v", err)
121	}
122	if reader.currentLine != 24 {
123		t.Errorf("expected %d for currentLine, got %d", 23, reader.currentLine)
124	}
125}
126
127func TestReadyCanReadSingleTagValue(t *testing.T) {
128	reader := &tvReader{}
129	err := reader.readNextLine("Tag:value")
130	if err != nil {
131		t.Errorf("got error when calling readNextLine: %v", err)
132	}
133	if len(reader.tvList) != 1 || reader.tvList[0].tag != "Tag" || reader.tvList[0].value != "value" {
134		t.Errorf("got invalid tag/value list: %v", reader.tvList)
135	}
136	if reader.currentLine != 1 {
137		t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
138	}
139	if reader.currentTag != "" {
140		t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
141	}
142	if reader.currentValue != "" {
143		t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
144	}
145}
146
147func TestReadyCanStripWhitespaceFromValue(t *testing.T) {
148	reader := &tvReader{}
149	err := reader.readNextLine("Tag:   value	  	 ")
150	if err != nil {
151		t.Errorf("got error when calling readNextLine: %v", err)
152	}
153	if len(reader.tvList) != 1 || reader.tvList[0].tag != "Tag" || reader.tvList[0].value != "value" {
154		t.Errorf("got invalid tag/value list: %v", reader.tvList)
155	}
156}
157
158func TestReadyCannotReadLineWithNoColon(t *testing.T) {
159	reader := &tvReader{}
160	err := reader.readNextLine("No colon should be an error")
161	if err == nil {
162		t.Errorf("should have gotten error when calling readNextLine")
163	}
164}
165
166func TestReadyTextTagSwitchesToMidtext(t *testing.T) {
167	reader := &tvReader{}
168	err := reader.readNextLine("Tag: <text>This begins a multiline value")
169	if err != nil {
170		t.Errorf("got error when calling readNextLine: %v", err)
171	}
172	if len(reader.tvList) != 0 {
173		t.Errorf("expected empty tag/value list, got %v", reader.tvList)
174	}
175	if !reader.midtext {
176		t.Errorf("expected midtext to be true, got false")
177	}
178	if reader.currentLine != 1 {
179		t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
180	}
181	if reader.currentTag != "Tag" {
182		t.Errorf("expected %s for currentTag, got %s", "Tag", reader.currentTag)
183	}
184	if reader.currentValue != "This begins a multiline value\n" {
185		t.Errorf("expected %s for currentValue, got %s", "This begins a multiline value\n", reader.currentValue)
186	}
187}
188
189func TestReadyTextTagAndClosingTagInOneLineFinishesRead(t *testing.T) {
190	reader := &tvReader{}
191	err := reader.readNextLine("Tag: <text>Just one line</text>")
192	if err != nil {
193		t.Errorf("got error when calling readNextLine: %v", err)
194	}
195	if len(reader.tvList) != 1 || reader.tvList[0].tag != "Tag" || reader.tvList[0].value != "Just one line" {
196		t.Errorf("got invalid tag/value list: %v", reader.tvList)
197	}
198	if reader.midtext {
199		t.Errorf("expected midtext to be false, got true")
200	}
201	if reader.currentLine != 1 {
202		t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
203	}
204	if reader.currentTag != "" {
205		t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
206	}
207	if reader.currentValue != "" {
208		t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
209	}
210}
211
212func TestCanReadMultilineTextAcrossThreeLines(t *testing.T) {
213	reader := &tvReader{}
214	err := reader.readNextLine("Tag: <text>This value")
215	if err != nil {
216		t.Errorf("got error when calling readNextLine: %v", err)
217	}
218	err = reader.readNextLine("is three")
219	if err != nil {
220		t.Errorf("got error when calling readNextLine: %v", err)
221	}
222	err = reader.readNextLine("lines long</text>")
223	if err != nil {
224		t.Errorf("got error when calling readNextLine: %v", err)
225	}
226
227	if len(reader.tvList) != 1 || reader.tvList[0].tag != "Tag" || reader.tvList[0].value != "This value\nis three\nlines long" {
228		t.Errorf("got invalid tag/value list: %v", reader.tvList)
229	}
230	if reader.midtext {
231		t.Errorf("expected midtext to be false, got true")
232	}
233	if reader.currentLine != 3 {
234		t.Errorf("expected %d for currentLine, got %d", 3, reader.currentLine)
235	}
236	if reader.currentTag != "" {
237		t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
238	}
239	if reader.currentValue != "" {
240		t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
241	}
242}
243
244func TestMidtextContinuesIfNoClosingText(t *testing.T) {
245	reader := &tvReader{}
246	reader.midtext = true
247	reader.currentLine = 1
248	reader.currentTag = "Multiline"
249	reader.currentValue = "First line\n"
250
251	err := reader.readNextLine("Second line")
252	if err != nil {
253		t.Errorf("got error when calling readNextLine: %v", err)
254	}
255
256	if len(reader.tvList) != 0 {
257		t.Errorf("expected empty tag/value list, got %v", reader.tvList)
258	}
259	if !reader.midtext {
260		t.Errorf("expected midtext to be true, got false")
261	}
262	if reader.currentLine != 2 {
263		t.Errorf("expected %d for currentLine, got %d", 2, reader.currentLine)
264	}
265	if reader.currentTag != "Multiline" {
266		t.Errorf("expected %s for currentTag, got %s", "Multiline", reader.currentTag)
267	}
268	if reader.currentValue != "First line\nSecond line\n" {
269		t.Errorf("expected %s for currentValue, got %s", "First line\nSecond line\n", reader.currentValue)
270	}
271}
272
273func TestMidtextFinishesIfReachingClosingText(t *testing.T) {
274	reader := &tvReader{}
275	reader.midtext = true
276	reader.currentLine = 1
277	reader.currentTag = "Multiline"
278	reader.currentValue = "First line\n"
279
280	err := reader.readNextLine("Second line</text>")
281	if err != nil {
282		t.Errorf("got error when calling readNextLine: %v", err)
283	}
284
285	if len(reader.tvList) != 1 || reader.tvList[0].tag != "Multiline" || reader.tvList[0].value != "First line\nSecond line" {
286		t.Errorf("got invalid tag/value list: %v", reader.tvList)
287	}
288	if reader.midtext {
289		t.Errorf("expected midtext to be false, got true")
290	}
291	if reader.currentLine != 2 {
292		t.Errorf("expected %d for currentLine, got %d", 2, reader.currentLine)
293	}
294	if reader.currentTag != "" {
295		t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
296	}
297	if reader.currentValue != "" {
298		t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
299	}
300}
301
302func TestReadyIgnoresCommentLines(t *testing.T) {
303	reader := &tvReader{}
304	err := reader.readNextLine("# this is a comment")
305	if err != nil {
306		t.Errorf("got error when calling readNextLine: %v", err)
307	}
308
309	if len(reader.tvList) != 0 {
310		t.Errorf("expected empty tag/value list, got %v", reader.tvList)
311	}
312	if reader.midtext {
313		t.Errorf("expected midtext to be false, got true")
314	}
315	if reader.currentLine != 1 {
316		t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
317	}
318	if reader.currentTag != "" {
319		t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
320	}
321	if reader.currentValue != "" {
322		t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
323	}
324}
325
326func TestMidtextIncludesCommentLines(t *testing.T) {
327	reader := &tvReader{}
328	reader.midtext = true
329	reader.currentLine = 1
330	reader.currentTag = "Multiline"
331	reader.currentValue = "First line\n"
332
333	err := reader.readNextLine("# This is part of multiline text")
334	if err != nil {
335		t.Errorf("got error when calling readNextLine: %v", err)
336	}
337
338	if len(reader.tvList) != 0 {
339		t.Errorf("expected empty tag/value list, got %v", reader.tvList)
340	}
341	if !reader.midtext {
342		t.Errorf("expected midtext to be true, got false")
343	}
344	if reader.currentLine != 2 {
345		t.Errorf("expected %d for currentLine, got %d", 2, reader.currentLine)
346	}
347	if reader.currentTag != "Multiline" {
348		t.Errorf("expected %s for currentTag, got %s", "Multiline", reader.currentTag)
349	}
350	if reader.currentValue != "First line\n# This is part of multiline text\n" {
351		t.Errorf("expected %s for currentValue, got %s", "First line\n# This is part of multiline text\n", reader.currentValue)
352	}
353}
354
355func TestReadyIgnoresEmptyLines(t *testing.T) {
356	reader := &tvReader{}
357	err := reader.readNextLine("")
358	if err != nil {
359		t.Errorf("got error when calling readNextLine: %v", err)
360	}
361
362	if len(reader.tvList) != 0 {
363		t.Errorf("expected empty tag/value list, got %v", reader.tvList)
364	}
365	if reader.midtext {
366		t.Errorf("expected midtext to be false, got true")
367	}
368	if reader.currentLine != 1 {
369		t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
370	}
371	if reader.currentTag != "" {
372		t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
373	}
374	if reader.currentValue != "" {
375		t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
376	}
377}
378
379func TestMidtextIncludesEmptyLines(t *testing.T) {
380	reader := &tvReader{}
381	reader.midtext = true
382	reader.currentLine = 1
383	reader.currentTag = "Multiline"
384	reader.currentValue = "First line\n"
385
386	err := reader.readNextLine("")
387	if err != nil {
388		t.Errorf("got error when calling readNextLine: %v", err)
389	}
390
391	if len(reader.tvList) != 0 {
392		t.Errorf("expected empty tag/value list, got %v", reader.tvList)
393	}
394	if !reader.midtext {
395		t.Errorf("expected midtext to be true, got false")
396	}
397	if reader.currentLine != 2 {
398		t.Errorf("expected %d for currentLine, got %d", 2, reader.currentLine)
399	}
400	if reader.currentTag != "Multiline" {
401		t.Errorf("expected %s for currentTag, got %s", "Multiline", reader.currentTag)
402	}
403	if reader.currentValue != "First line\n\n" {
404		t.Errorf("expected %s for currentValue, got %s", "First line\n\n", reader.currentValue)
405	}
406}
407
408func TestReadyIgnoresWhitespaceOnlyLines(t *testing.T) {
409	reader := &tvReader{}
410	err := reader.readNextLine("   \t\t\t ")
411	if err != nil {
412		t.Errorf("got error when calling readNextLine: %v", err)
413	}
414
415	if len(reader.tvList) != 0 {
416		t.Errorf("expected empty tag/value list, got %v", reader.tvList)
417	}
418	if reader.midtext {
419		t.Errorf("expected midtext to be false, got true")
420	}
421	if reader.currentLine != 1 {
422		t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
423	}
424	if reader.currentTag != "" {
425		t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
426	}
427	if reader.currentValue != "" {
428		t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
429	}
430}
431
432func TestMidtextIncludesWhitespaceOnlyLines(t *testing.T) {
433	reader := &tvReader{}
434	reader.midtext = true
435	reader.currentLine = 1
436	reader.currentTag = "Multiline"
437	reader.currentValue = "First line\n"
438
439	err := reader.readNextLine("     \t\t ")
440	if err != nil {
441		t.Errorf("got error when calling readNextLine: %v", err)
442	}
443
444	if len(reader.tvList) != 0 {
445		t.Errorf("expected empty tag/value list, got %v", reader.tvList)
446	}
447	if !reader.midtext {
448		t.Errorf("expected midtext to be true, got false")
449	}
450	if reader.currentLine != 2 {
451		t.Errorf("expected %d for currentLine, got %d", 2, reader.currentLine)
452	}
453	if reader.currentTag != "Multiline" {
454		t.Errorf("expected %s for currentTag, got %s", "Multiline", reader.currentTag)
455	}
456	if reader.currentValue != "First line\n     \t\t \n" {
457		t.Errorf("expected %s for currentValue, got %s", "First line\n     \t\t \n", reader.currentValue)
458	}
459}
460
461func TestReadyIgnoresSpacesBeforeTag(t *testing.T) {
462	reader := &tvReader{}
463	err := reader.readNextLine("    \t Tag:value")
464	if err != nil {
465		t.Errorf("got error when calling readNextLine: %v", err)
466	}
467	if len(reader.tvList) != 1 || reader.tvList[0].tag != "Tag" || reader.tvList[0].value != "value" {
468		t.Errorf("got invalid tag/value list: %v", reader.tvList)
469	}
470	if reader.currentLine != 1 {
471		t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
472	}
473	if reader.currentTag != "" {
474		t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
475	}
476	if reader.currentValue != "" {
477		t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
478	}
479}
480
481func TestReadyIgnoresSpacesBeforeCommentLines(t *testing.T) {
482	reader := &tvReader{}
483	err := reader.readNextLine("     \t\t  # this is a comment")
484	if err != nil {
485		t.Errorf("got error when calling readNextLine: %v", err)
486	}
487
488	if len(reader.tvList) != 0 {
489		t.Errorf("expected empty tag/value list, got %v", reader.tvList)
490	}
491	if reader.midtext {
492		t.Errorf("expected midtext to be false, got true")
493	}
494	if reader.currentLine != 1 {
495		t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
496	}
497	if reader.currentTag != "" {
498		t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
499	}
500	if reader.currentValue != "" {
501		t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
502	}
503}
504
505func TestReadyIgnoresSpacesBetweenTagAndColon(t *testing.T) {
506	reader := &tvReader{}
507	err := reader.readNextLine("Tag   \t :value")
508	if err != nil {
509		t.Errorf("got error when calling readNextLine: %v", err)
510	}
511	if len(reader.tvList) != 1 || reader.tvList[0].tag != "Tag" || reader.tvList[0].value != "value" {
512		t.Errorf("got invalid tag/value list: %v", reader.tvList)
513	}
514	if reader.currentLine != 1 {
515		t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
516	}
517	if reader.currentTag != "" {
518		t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
519	}
520	if reader.currentValue != "" {
521		t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
522	}
523}
524
525func TestReadyIgnoresSpacesBetweenColonAndValue(t *testing.T) {
526	reader := &tvReader{}
527	err := reader.readNextLine("Tag:    \t value")
528	if err != nil {
529		t.Errorf("got error when calling readNextLine: %v", err)
530	}
531	if len(reader.tvList) != 1 || reader.tvList[0].tag != "Tag" || reader.tvList[0].value != "value" {
532		t.Errorf("got invalid tag/value list: %v", reader.tvList)
533	}
534	if reader.currentLine != 1 {
535		t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
536	}
537	if reader.currentTag != "" {
538		t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
539	}
540	if reader.currentValue != "" {
541		t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
542	}
543}
544
545func TestReadyIgnoresSpacesAfterEndOfValue(t *testing.T) {
546	reader := &tvReader{}
547	err := reader.readNextLine("Tag:value   \t  ")
548	if err != nil {
549		t.Errorf("got error when calling readNextLine: %v", err)
550	}
551	if len(reader.tvList) != 1 || reader.tvList[0].tag != "Tag" || reader.tvList[0].value != "value" {
552		t.Errorf("got invalid tag/value list: %v", reader.tvList)
553	}
554	if reader.currentLine != 1 {
555		t.Errorf("expected %d for currentLine, got %d", 1, reader.currentLine)
556	}
557	if reader.currentTag != "" {
558		t.Errorf("expected empty string for currentTag, got %s", reader.currentTag)
559	}
560	if reader.currentValue != "" {
561		t.Errorf("expected empty string for currentValue, got %s", reader.currentValue)
562	}
563}
564