kvfile_test.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. package kvfile
  2. import (
  3. "bufio"
  4. "os"
  5. "path/filepath"
  6. "strings"
  7. "testing"
  8. "gotest.tools/v3/assert"
  9. is "gotest.tools/v3/assert/cmp"
  10. )
  11. // Test Parse for a non existent file.
  12. func TestParseNonExistentFile(t *testing.T) {
  13. _, err := Parse("no_such_file", nil)
  14. assert.Check(t, is.ErrorType(err, os.IsNotExist))
  15. }
  16. // Test Parse from a file with a lookup function.
  17. func TestParseWithLookup(t *testing.T) {
  18. content := `# comment=
  19. VAR=VAR_VALUE
  20. EMPTY_VAR=
  21. UNDEFINED_VAR
  22. DEFINED_VAR
  23. `
  24. vars := map[string]string{
  25. "DEFINED_VAR": "defined-value",
  26. }
  27. lookupFn := func(name string) (string, bool) {
  28. v, ok := vars[name]
  29. return v, ok
  30. }
  31. fileName := filepath.Join(t.TempDir(), "envfile")
  32. err := os.WriteFile(fileName, []byte(content), 0o644)
  33. assert.NilError(t, err)
  34. variables, err := Parse(fileName, lookupFn)
  35. assert.NilError(t, err)
  36. expectedLines := []string{"VAR=VAR_VALUE", "EMPTY_VAR=", "DEFINED_VAR=defined-value"}
  37. assert.Check(t, is.DeepEqual(variables, expectedLines))
  38. }
  39. // Test ParseEnvFile for a file with a few well formatted lines
  40. func TestParseFromReaderGoodFile(t *testing.T) {
  41. content := `foo=bar
  42. baz=quux
  43. # comment
  44. _foobar=foobaz
  45. with.dots=working
  46. and_underscore=working too
  47. `
  48. // Adding a newline + a line with pure whitespace.
  49. // This is being done like this instead of the block above
  50. // because it's common for editors to trim trailing whitespace
  51. // from lines, which becomes annoying since that's the
  52. // exact thing we need to test.
  53. content += "\n \t "
  54. lines, err := ParseFromReader(strings.NewReader(content), nil)
  55. assert.NilError(t, err)
  56. expectedLines := []string{
  57. "foo=bar",
  58. "baz=quux",
  59. "_foobar=foobaz",
  60. "with.dots=working",
  61. "and_underscore=working too",
  62. }
  63. assert.Check(t, is.DeepEqual(lines, expectedLines))
  64. }
  65. // Test ParseFromReader for an empty file
  66. func TestParseFromReaderEmptyFile(t *testing.T) {
  67. lines, err := ParseFromReader(strings.NewReader(""), nil)
  68. assert.NilError(t, err)
  69. assert.Check(t, is.Len(lines, 0))
  70. }
  71. // Test ParseFromReader for a badly formatted file
  72. func TestParseFromReaderBadlyFormattedFile(t *testing.T) {
  73. content := `foo=bar
  74. f =quux
  75. `
  76. _, err := ParseFromReader(strings.NewReader(content), nil)
  77. const expectedMessage = "variable 'f ' contains whitespaces"
  78. assert.Check(t, is.ErrorContains(err, expectedMessage))
  79. }
  80. // Test ParseFromReader for a file with a line exceeding bufio.MaxScanTokenSize
  81. func TestParseFromReaderLineTooLongFile(t *testing.T) {
  82. content := "foo=" + strings.Repeat("a", bufio.MaxScanTokenSize+42)
  83. _, err := ParseFromReader(strings.NewReader(content), nil)
  84. const expectedMessage = "bufio.Scanner: token too long"
  85. assert.Check(t, is.ErrorContains(err, expectedMessage))
  86. }
  87. // ParseEnvFile with a random file, pass through
  88. func TestParseFromReaderRandomFile(t *testing.T) {
  89. content := `first line
  90. another invalid line`
  91. _, err := ParseFromReader(strings.NewReader(content), nil)
  92. const expectedMessage = "variable 'first line' contains whitespaces"
  93. assert.Check(t, is.ErrorContains(err, expectedMessage))
  94. }
  95. // Test ParseFromReader with a lookup function.
  96. func TestParseFromReaderWithLookup(t *testing.T) {
  97. content := `# comment=
  98. VAR=VAR_VALUE
  99. EMPTY_VAR=
  100. UNDEFINED_VAR
  101. DEFINED_VAR
  102. `
  103. vars := map[string]string{
  104. "DEFINED_VAR": "defined-value",
  105. }
  106. lookupFn := func(name string) (string, bool) {
  107. v, ok := vars[name]
  108. return v, ok
  109. }
  110. variables, err := ParseFromReader(strings.NewReader(content), lookupFn)
  111. assert.NilError(t, err)
  112. expectedLines := []string{"VAR=VAR_VALUE", "EMPTY_VAR=", "DEFINED_VAR=defined-value"}
  113. assert.Check(t, is.DeepEqual(variables, expectedLines))
  114. }
  115. // Test ParseFromReader with empty variable name
  116. func TestParseFromReaderWithNoName(t *testing.T) {
  117. content := `# comment=
  118. =blank variable names are an error case
  119. `
  120. _, err := ParseFromReader(strings.NewReader(content), nil)
  121. const expectedMessage = "no variable name on line '=blank variable names are an error case'"
  122. assert.Check(t, is.ErrorContains(err, expectedMessage))
  123. }