parse_test.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. package attl
  2. import "testing"
  3. import "reflect"
  4. type testCase struct {
  5. ParseFunc
  6. input string
  7. index int
  8. expectedIndex int
  9. expectError bool
  10. expectedValue Value
  11. }
  12. func (tc *testCase) Run(t *testing.T) {
  13. t.Logf("Test case input: %s", tc.input)
  14. res, err := tc.ParseFunc([]rune(tc.input), &tc.index)
  15. if tc.expectError {
  16. if err == nil {
  17. t.Errorf("expected parse error")
  18. return
  19. }
  20. } else {
  21. if err != nil {
  22. t.Errorf("error: unexpected parse error at %d: %v", tc.index, err)
  23. return
  24. }
  25. }
  26. if tc.index != tc.expectedIndex {
  27. if err == nil {
  28. t.Errorf("error: index not correct: %d <> %d", tc.index, tc.expectedIndex)
  29. }
  30. }
  31. if tc.expectedValue == nil {
  32. if res != nil {
  33. t.Errorf("error: expected nil value, got %v", res)
  34. } else {
  35. t.Logf("Test case value: nil")
  36. }
  37. } else {
  38. if res == nil {
  39. t.Errorf("error: expected value %v was nil", tc.expectedValue)
  40. } else {
  41. t.Logf("Test case value: %v", res)
  42. se := tc.expectedValue.String()
  43. so := res.String()
  44. if so != se {
  45. t.Errorf("error: value is not as expected: %s <-> %s", so, se)
  46. } else {
  47. if !reflect.DeepEqual(tc.expectedValue, res) {
  48. t.Errorf("error: values are not deeply equal: %s <-> %s", so, se)
  49. }
  50. }
  51. }
  52. }
  53. rs := []rune(tc.input)
  54. b := string(rs[0:tc.index])
  55. a := string(rs[tc.index:len(rs)])
  56. t.Logf("Test case index: %s|%s", b, a)
  57. }
  58. func TestParseComment(t *testing.T) {
  59. tcs := []testCase{
  60. testCase{ParseComment, "# comment\nnot comment", 0, 9, false, Comment("# comment")},
  61. testCase{ParseComment, "not comment\n#comment\n", 0, 0, false, nil},
  62. testCase{ParseComment, "# comment\nnot comment", 9, 9, false, nil},
  63. }
  64. for i, tc := range tcs {
  65. t.Logf("Case: %d", i+1)
  66. tc.Run(t)
  67. }
  68. }
  69. func TestParseWs(t *testing.T) {
  70. tcs := []testCase{
  71. testCase{ParseWs, "# comment ", 0, 0, false, nil},
  72. testCase{ParseWs, "1234567890 ", 0, 0, false, nil},
  73. testCase{ParseWs, "-1234567890 ", 0, 0, false, nil},
  74. testCase{ParseWs, "+1234567890 ", 0, 0, false, nil},
  75. testCase{ParseWs, "`string` ", 0, 0, false, nil},
  76. testCase{ParseWs, `"string" `, 0, 0, false, nil},
  77. testCase{ParseWs, "word ", 0, 0, false, nil},
  78. testCase{ParseWs, " \tword ", 0, 2, false, String(" \t")},
  79. }
  80. for i, tc := range tcs {
  81. t.Logf("Case: %d", i+1)
  82. tc.Run(t)
  83. }
  84. }
  85. func TestParseGetter(t *testing.T) {
  86. tcs := []testCase{
  87. testCase{ParseGetter, "not a getter ", 0, 0, false, nil},
  88. testCase{ParseGetter, "$# comment ", 0, 0, true, nil},
  89. testCase{ParseGetter, "$ bad space ", 0, 0, true, nil},
  90. testCase{ParseGetter, "$1234567890 ", 0, 11, false, Getter{Int(+1234567890)}},
  91. testCase{ParseGetter, "$-1234567890 ", 0, 12, false, Getter{Int(-1234567890)}},
  92. testCase{ParseGetter, "$+1234567890 ", 0, 12, false, Getter{Int(+1234567890)}},
  93. testCase{ParseGetter, "$`string` ", 0, 9, false, Getter{String("string")}},
  94. testCase{ParseGetter, `$"string" `, 0, 9, false, Getter{String("string")}},
  95. testCase{ParseGetter, "$word ", 0, 5, false, Getter{Word("word")}},
  96. testCase{ParseGetter, "$µ_rd ", 0, 5, false, Getter{Word("µ_rd")}},
  97. testCase{ParseGetter, "$wo09 ", 0, 5, false, Getter{Word("wo09")}},
  98. }
  99. for i, tc := range tcs {
  100. t.Logf("Case: %d", i+1)
  101. tc.Run(t)
  102. }
  103. }
  104. func TestParseInteger(t *testing.T) {
  105. tcs := []testCase{
  106. testCase{ParseInteger, "01234567890 ", 0, 11, false, Int(1234567890)},
  107. testCase{ParseInteger, "-1234567890 ", 0, 11, false, Int(-1234567890)},
  108. testCase{ParseInteger, "+1234567890 ", 0, 11, false, Int(1234567890)},
  109. testCase{ParseInteger, "+1234567890", 0, 11, true, nil},
  110. testCase{ParseInteger, "not an integer", 0, 0, false, nil},
  111. }
  112. for i, tc := range tcs {
  113. t.Logf("Case: %d", i+1)
  114. tc.Run(t)
  115. }
  116. }
  117. func TestParseString(t *testing.T) {
  118. tcs := []testCase{
  119. testCase{ParseString, `"string"`, 0, 8, false, String("string")},
  120. testCase{ParseString, `"string\"\n"`, 0, 12, false, String("string\"\n")},
  121. testCase{ParseString, `"bad `, 0, 12, true, nil},
  122. testCase{ParseString, `not a string`, 0, 0, false, nil},
  123. }
  124. for i, tc := range tcs {
  125. t.Logf("Case: %d", i+1)
  126. tc.Run(t)
  127. }
  128. }
  129. func TestParseRawString(t *testing.T) {
  130. tcs := []testCase{
  131. testCase{ParseRawString, "`string` ", 0, 8, false, String("string")},
  132. testCase{ParseRawString, "`string\"quote` ", 0, 14, false,
  133. String("string\"quote")},
  134. testCase{ParseRawString, "`bad ", 0, 11, true, nil},
  135. testCase{ParseRawString, "not a string` ", 0, 0, false, nil},
  136. }
  137. for i, tc := range tcs {
  138. t.Logf("Case: %d", i+1)
  139. tc.Run(t)
  140. }
  141. }
  142. func TestParseWord(t *testing.T) {
  143. tcs := []testCase{
  144. testCase{ParseWord, "word ", 0, 4, false, Word("word")},
  145. testCase{ParseWord, "word\n", 0, 4, false, Word("word")},
  146. testCase{ParseWord, "word; ", 0, 4, false, Word("word")},
  147. }
  148. for i, tc := range tcs {
  149. t.Logf("Case: %d", i+1)
  150. tc.Run(t)
  151. }
  152. }
  153. func TestParseLiteral(t *testing.T) {
  154. tcs := []testCase{
  155. testCase{ParseLiteral, "# comment ", 0, 0, false, nil},
  156. testCase{ParseLiteral, " \t ", 0, 0, false, nil},
  157. testCase{ParseLiteral, "1234567890 ", 0, 10, false, Int(1234567890)},
  158. testCase{ParseLiteral, "-1234567890 ", 0, 11, false, Int(-1234567890)},
  159. testCase{ParseLiteral, "+1234567890 ", 0, 11, false, Int(1234567890)},
  160. testCase{ParseLiteral, "`string` ", 0, 8, false, String("string")},
  161. testCase{ParseLiteral, `"string" `, 0, 8, false, String("string")},
  162. testCase{ParseLiteral, "word ", 0, 4, false, Word("word")},
  163. testCase{ParseLiteral, "µ_rd ", 0, 4, false, Word("µ_rd")},
  164. testCase{ParseLiteral, "wo09 ", 0, 4, false, Word("wo09")},
  165. }
  166. for i, tc := range tcs {
  167. t.Logf("Case: %d", i+1)
  168. tc.Run(t)
  169. }
  170. }
  171. func TestParseParameters(t *testing.T) {
  172. tcs := []testCase{
  173. testCase{ParseParameters, " world\n", 0, 6, false, List{Word("world")}},
  174. testCase{ParseParameters, ` world 7 "foo"` + "`\n", 0, 14, false,
  175. List{Word("world"), Int(7), String("foo")},
  176. },
  177. }
  178. for i, tc := range tcs {
  179. t.Logf("Case: %d", i+1)
  180. tc.Run(t)
  181. }
  182. }
  183. func TestParseOrder(t *testing.T) {
  184. tcs := []testCase{
  185. testCase{ParseOrder, "hello ", 0, 5, false, Word("hello")},
  186. testCase{ParseOrder, "1 ", 0, 1, false, Int(1)},
  187. }
  188. for i, tc := range tcs {
  189. t.Logf("Case: %d", i+1)
  190. tc.Run(t)
  191. }
  192. }
  193. func TestParseCommand(t *testing.T) {
  194. tcs := []testCase{
  195. testCase{ParseCommand, "hello world\n", 0, 11, false,
  196. Command{Word("hello"), List{Word("world")}},
  197. },
  198. }
  199. for i, tc := range tcs {
  200. t.Logf("Case: %d", i+1)
  201. tc.Run(t)
  202. }
  203. }
  204. func TestParseEvaluation(t *testing.T) {
  205. tcs := []testCase{
  206. testCase{ParseEvaluation, "[hello world]", 0, 13, false,
  207. Evaluation{Command{Word("hello"), List{Word("world")}}},
  208. },
  209. testCase{ParseEvaluation, "[hello 123 ]", 0, 12, false,
  210. Evaluation{Command{Word("hello"), List{Int(123)}}},
  211. },
  212. }
  213. for i, tc := range tcs {
  214. t.Logf("Case: %d", i+1)
  215. tc.Run(t)
  216. }
  217. }
  218. func TestParseAStatement(t *testing.T) {
  219. tcs := []testCase{
  220. testCase{ParseStatement, " hello world\n", 0, 12, false,
  221. Command{Word("hello"), List{Word("world")}},
  222. },
  223. testCase{ParseStatement, " hello;world;", 0, 6, false,
  224. Command{Word("hello"), List{}},
  225. },
  226. }
  227. for i, tc := range tcs {
  228. t.Logf("Case: %d", i+1)
  229. tc.Run(t)
  230. }
  231. }
  232. func TestParseStatements(t *testing.T) {
  233. tcs := []testCase{
  234. testCase{ParseStatements, "\n\n\n", 0, 3, false,
  235. List{},
  236. },
  237. testCase{ParseStatements, "\n\n \n", 0, 4, false,
  238. List{},
  239. },
  240. testCase{ParseStatements, "hello world\n", 0, 12, false,
  241. List{Command{Word("hello"), List{Word("world")}}},
  242. },
  243. testCase{ParseStatements, "hello;world;", 0, 12, false,
  244. List{Command{Word("hello"), List{}}, Command{Word("world"), List{}}},
  245. },
  246. testCase{ParseStatements, "hello \n world \n\n", 0, 16, false,
  247. List{Command{Word("hello"), List{}}, Command{Word("world"), List{}}},
  248. },
  249. }
  250. for i, tc := range tcs {
  251. t.Logf("Case: %d", i+1)
  252. tc.Run(t)
  253. }
  254. }
  255. func TestParseBlock(t *testing.T) {
  256. tcs := []testCase{
  257. testCase{ParseBlock, "{hello world}", 0, 13, false,
  258. Block{List{Command{Word("hello"), List{Word("world")}}}},
  259. },
  260. testCase{ParseBlock, "{hello;world}", 0, 13, false,
  261. Block{List{Command{Word("hello"), List{}}, Command{Word("world"), List{}}}},
  262. },
  263. testCase{ParseBlock, "{hello\nworld}", 0, 13, false,
  264. Block{List{Command{Word("hello"), List{}}, Command{Word("world"), List{}}}},
  265. },
  266. testCase{ParseBlock, "{ hello\n world\n}", 0, 16, false,
  267. Block{List{Command{Word("hello"), List{}}, Command{Word("world"), List{}}}},
  268. },
  269. testCase{ParseBlock, "{ #Comment\n hello\n world\n}", 0, 26, false,
  270. Block{List{Comment("#Comment"), Command{Word("hello"), List{}}, Command{Word("world"), List{}}}}},
  271. }
  272. for i, tc := range tcs {
  273. t.Logf("Case: %d", i+1)
  274. tc.Run(t)
  275. }
  276. }
  277. func TestParse(t *testing.T) {
  278. script1 := `
  279. # Comment
  280. print "Hello world!"
  281. `
  282. res1 := Block{List{Comment("# Comment"), Command{Word("print"), List{String("Hello world!")}}}}
  283. script2 := `
  284. # Comment
  285. print "Hello world!"
  286. `
  287. res2 := Block{List{Comment("# Comment"), Command{Word("print"), List{String("Hello world!")}}}}
  288. tcs := []testCase{
  289. testCase{ParseScript, script1, 0, len(script1), false, res1},
  290. testCase{ParseScript, script2, 0, len(script1), false, res2},
  291. }
  292. for i, tc := range tcs {
  293. t.Logf("Case: %d", i+1)
  294. tc.Run(t)
  295. }
  296. }
  297. func TestParseAndRun(t *testing.T) {
  298. script1 := `
  299. # Comment
  300. print "Hello world!"
  301. `
  302. parsed, err := Parse(script1)
  303. if err != nil {
  304. t.Errorf("Parse error: %v", err)
  305. return
  306. }
  307. if parsed == nil {
  308. t.Errorf("No parse results error: %v", parsed)
  309. return
  310. }
  311. env := &Environment{}
  312. env.Push()
  313. env.Define("print", Proc(func(e *Environment, args ...Value) (Value, Effect) {
  314. var msg string
  315. Args(args, &msg)
  316. print(msg, "\n")
  317. return nil, nil
  318. }), 0)
  319. parsed.Eval(env)
  320. }
  321. type iTestCase struct {
  322. in string
  323. ex string
  324. expectError bool
  325. args []Value
  326. }
  327. func (tc *iTestCase) Run(t *testing.T, e Environment) {
  328. t.Logf("Test case input: %s", tc.in)
  329. res := e.Interpolate(tc.in, tc.args...)
  330. t.Logf("Test case result: %v", res)
  331. if res != tc.ex {
  332. t.Errorf("error: value not expected: %s <-> %s", res, tc.ex)
  333. }
  334. }
  335. func TestInterpolate(t *testing.T) {
  336. e := Environment{}
  337. e.Push()
  338. e.Define("foo", String("{world}"), 0)
  339. tcs := []iTestCase{
  340. iTestCase{`hello {world}`, `hello {world}`, false, []Value{}},
  341. iTestCase{`hello ${foo}`, `hello {world}`, false, []Value{}},
  342. iTestCase{`hello $${foo}`, `hello ${foo}`, false, []Value{}},
  343. iTestCase{`hello ${1}`, `hello {world}`, false, []Value{String("{world}")}},
  344. }
  345. for i, tc := range tcs {
  346. t.Logf("Case: %d", i+1)
  347. tc.Run(t, e)
  348. }
  349. }