tokenize_test.go 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. package tokenize
  2. import "fmt"
  3. import "testing"
  4. func Test_tokenize(t *testing.T) {
  5. var test_cases = []struct {
  6. test_str string
  7. want_result tokenizeResult
  8. }{
  9. // emptiness
  10. {"", tokenizeResult{tokens: []string{}}},
  11. // unquoted whitespace
  12. {" ", tokenizeResult{tokens: []string{}}},
  13. {"\t", tokenizeResult{tokens: []string{}}},
  14. {"\n", tokenizeResult{tokens: []string{}}},
  15. {" \t\n", tokenizeResult{tokens: []string{}}},
  16. {" \tfoo", tokenizeResult{tokens: []string{"foo"}}},
  17. {"foo ", tokenizeResult{tokens: []string{"foo"}}},
  18. {"foo bar", tokenizeResult{tokens: []string{"foo", "bar"}}},
  19. {"foo\nbar", tokenizeResult{tokens: []string{"foo", "bar"}}},
  20. {"foo\tbar", tokenizeResult{tokens: []string{"foo", "bar"}}},
  21. // single quotes
  22. {"'", tokenizeResult{tokens: []string{}, code: tokenizeResultCodeMissingEndSingleQuote}},
  23. {"''", tokenizeResult{tokens: []string{""}}},
  24. {"fo''o", tokenizeResult{tokens: []string{"foo"}}},
  25. {"foo '' bar", tokenizeResult{tokens: []string{"foo", "", "bar"}}},
  26. {"foo 'and' bar", tokenizeResult{tokens: []string{"foo", "and", "bar"}}},
  27. {"foo '\\\t\n' bar", tokenizeResult{tokens: []string{"foo", "\\\t\n", "bar"}}},
  28. {"foo ' space bar '", tokenizeResult{tokens: []string{"foo", " space bar "}}},
  29. {"foo 'John \"Spaceman\" Doe'", tokenizeResult{tokens: []string{"foo", "John \"Spaceman\" Doe"}}},
  30. // double quotes
  31. {"\"", tokenizeResult{tokens: []string{}, code: tokenizeResultCodeMissingEndDoubleQuote}},
  32. {"\"\"", tokenizeResult{tokens: []string{""}}},
  33. {"fo\"\"o", tokenizeResult{tokens: []string{"foo"}}},
  34. {"foo \"\" bar", tokenizeResult{tokens: []string{"foo", "", "bar"}}},
  35. {"foo \"and\" bar", tokenizeResult{tokens: []string{"foo", "and", "bar"}}},
  36. {"foo \"\\\t\n\" bar", tokenizeResult{tokens: []string{"foo", "\\\t\n", "bar"}}},
  37. {"foo \" space bar \"", tokenizeResult{tokens: []string{"foo", " space bar "}}},
  38. {"foo \"Joe's lunch\"", tokenizeResult{tokens: []string{"foo", "Joe's lunch"}}},
  39. // lone backslash
  40. {"\\", tokenizeResult{tokens: []string{}, code: tokenizeResultCodeMissingEscapedCharacter}},
  41. {"\\\\", tokenizeResult{tokens: []string{"\\"}}},
  42. {"\\a", tokenizeResult{tokens: []string{"a"}}},
  43. {"\\?", tokenizeResult{tokens: []string{"?"}}},
  44. {"\\$", tokenizeResult{tokens: []string{"$"}}},
  45. {"\\ ", tokenizeResult{tokens: []string{" "}}},
  46. {"\\\t", tokenizeResult{tokens: []string{"\t"}}},
  47. {"\\\n", tokenizeResult{tokens: []string{"\n"}}},
  48. {"fo\\o", tokenizeResult{tokens: []string{"foo"}}},
  49. {"fo\\\\o", tokenizeResult{tokens: []string{"fo\\o"}}},
  50. {"foo \\ bar", tokenizeResult{tokens: []string{"foo", " bar"}}},
  51. {"foo \\\\ bar", tokenizeResult{tokens: []string{"foo", "\\", "bar"}}},
  52. {"foo \\'bar\\' baz", tokenizeResult{tokens: []string{"foo", "'bar'", "baz"}}},
  53. //
  54. }
  55. for _, tc := range test_cases {
  56. t.Run(fmt.Sprintf("%q", tc.test_str), func(t *testing.T) {
  57. have_result := tokenize(tc.test_str)
  58. if have_result.code != tc.want_result.code {
  59. t.Errorf("unexpected result .code: got %s, want %s in %v", have_result.code, tc.want_result.code, have_result)
  60. return
  61. }
  62. if have_result.err_loc != tc.want_result.err_loc {
  63. t.Errorf("unexpected result .err_loc: got %d, want %d in %v", have_result.err_loc, tc.want_result.err_loc, have_result)
  64. return
  65. }
  66. if len(have_result.tokens) != len(tc.want_result.tokens) {
  67. t.Errorf("unexpected number of result .tokens: got %d, want %d in %v", len(have_result.tokens), len(tc.want_result.tokens), have_result)
  68. return
  69. }
  70. for i := range have_result.tokens {
  71. if have_result.tokens[i] == tc.want_result.tokens[i] {
  72. continue
  73. }
  74. t.Errorf("unexpected token in result .tokens[%d]: got %q, want %q in %v", i, have_result.tokens[i], tc.want_result.tokens[i], have_result)
  75. return
  76. }
  77. })
  78. }
  79. }
  80. func Test_reader_tossUntilNeitherOf(t *testing.T) {
  81. var test_cases = []struct {
  82. test_data string
  83. test_needles string
  84. test_startpos uint
  85. want_endpos uint
  86. want_ok bool
  87. }{
  88. {"", "", 0, 0, false},
  89. {"", "x", 0, 0, false},
  90. {"", "xy", 0, 0, false},
  91. {"x", "", 0, 0, false},
  92. {"x", "x", 0, 1, true},
  93. {"x", "xy", 0, 1, true},
  94. {"x", "yx", 0, 1, true},
  95. {"xa", "x", 0, 1, true},
  96. {"xa", "xy", 0, 1, true},
  97. {"xa", "yx", 0, 1, true},
  98. {"xya", "x", 0, 1, true},
  99. {"xya", "xy", 0, 2, true},
  100. {"xya", "yx", 0, 2, true},
  101. {"xxya", "x", 1, 2, true},
  102. {"xxya", "xy", 1, 3, true},
  103. {"xxya", "yx", 1, 3, true},
  104. }
  105. for _, tc := range test_cases {
  106. t.Run(fmt.Sprintf("%q[%d:]-%q", tc.test_data, tc.test_startpos, tc.test_needles), func(t *testing.T) {
  107. test_reader := reader{data: tc.test_data}
  108. test_reader.pos = tc.test_startpos
  109. have_ok := test_reader.tossUntilNeitherOf(tc.test_needles)
  110. if test_reader.pos != tc.want_endpos {
  111. t.Errorf("unexpected position after toss: got %d, want %d", test_reader.pos, tc.want_endpos)
  112. return
  113. }
  114. if have_ok != tc.want_ok {
  115. t.Errorf("unexpected ok: got %v, want %v", have_ok, tc.want_ok)
  116. return
  117. }
  118. })
  119. }
  120. }