template_test.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. package fasttemplate
  2. import (
  3. "bytes"
  4. "errors"
  5. "io"
  6. "testing"
  7. )
  8. func TestEmptyTemplate(t *testing.T) {
  9. tpl := New("", "[", "]")
  10. s := tpl.ExecuteString(map[string]interface{}{"foo": "bar", "aaa": "bbb"})
  11. if s != "" {
  12. t.Fatalf("unexpected string returned %q. Expected empty string", s)
  13. }
  14. }
  15. func TestEmptyTagStart(t *testing.T) {
  16. expectPanic(t, func() { NewTemplate("foobar", "", "]") })
  17. }
  18. func TestEmptyTagEnd(t *testing.T) {
  19. expectPanic(t, func() { NewTemplate("foobar", "[", "") })
  20. }
  21. func TestNoTags(t *testing.T) {
  22. template := "foobar"
  23. tpl := New(template, "[", "]")
  24. s := tpl.ExecuteString(map[string]interface{}{"foo": "bar", "aaa": "bbb"})
  25. if s != template {
  26. t.Fatalf("unexpected template value %q. Expected %q", s, template)
  27. }
  28. }
  29. func TestEmptyTagName(t *testing.T) {
  30. template := "foo[]bar"
  31. tpl := New(template, "[", "]")
  32. s := tpl.ExecuteString(map[string]interface{}{"": "111", "aaa": "bbb"})
  33. result := "foo111bar"
  34. if s != result {
  35. t.Fatalf("unexpected template value %q. Expected %q", s, result)
  36. }
  37. }
  38. func TestOnlyTag(t *testing.T) {
  39. template := "[foo]"
  40. tpl := New(template, "[", "]")
  41. s := tpl.ExecuteString(map[string]interface{}{"foo": "111", "aaa": "bbb"})
  42. result := "111"
  43. if s != result {
  44. t.Fatalf("unexpected template value %q. Expected %q", s, result)
  45. }
  46. }
  47. func TestStartWithTag(t *testing.T) {
  48. template := "[foo]barbaz"
  49. tpl := New(template, "[", "]")
  50. s := tpl.ExecuteString(map[string]interface{}{"foo": "111", "aaa": "bbb"})
  51. result := "111barbaz"
  52. if s != result {
  53. t.Fatalf("unexpected template value %q. Expected %q", s, result)
  54. }
  55. }
  56. func TestEndWithTag(t *testing.T) {
  57. template := "foobar[foo]"
  58. tpl := New(template, "[", "]")
  59. s := tpl.ExecuteString(map[string]interface{}{"foo": "111", "aaa": "bbb"})
  60. result := "foobar111"
  61. if s != result {
  62. t.Fatalf("unexpected template value %q. Expected %q", s, result)
  63. }
  64. }
  65. func TestTemplateReset(t *testing.T) {
  66. template := "foo{bar}baz"
  67. tpl := New(template, "{", "}")
  68. s := tpl.ExecuteString(map[string]interface{}{"bar": "111"})
  69. result := "foo111baz"
  70. if s != result {
  71. t.Fatalf("unexpected template value %q. Expected %q", s, result)
  72. }
  73. template = "[xxxyyyzz"
  74. if err := tpl.Reset(template, "[", "]"); err == nil {
  75. t.Fatalf("expecting error for unclosed tag on %q", template)
  76. }
  77. template = "[xxx]yyy[zz]"
  78. if err := tpl.Reset(template, "[", "]"); err != nil {
  79. t.Fatalf("unexpected error: %s", err)
  80. }
  81. s = tpl.ExecuteString(map[string]interface{}{"xxx": "11", "zz": "2222"})
  82. result = "11yyy2222"
  83. if s != result {
  84. t.Fatalf("unexpected template value %q. Expected %q", s, result)
  85. }
  86. }
  87. func TestDuplicateTags(t *testing.T) {
  88. template := "[foo]bar[foo][foo]baz"
  89. tpl := New(template, "[", "]")
  90. s := tpl.ExecuteString(map[string]interface{}{"foo": "111", "aaa": "bbb"})
  91. result := "111bar111111baz"
  92. if s != result {
  93. t.Fatalf("unexpected template value %q. Expected %q", s, result)
  94. }
  95. }
  96. func TestMultipleTags(t *testing.T) {
  97. template := "foo[foo]aa[aaa]ccc"
  98. tpl := New(template, "[", "]")
  99. s := tpl.ExecuteString(map[string]interface{}{"foo": "111", "aaa": "bbb"})
  100. result := "foo111aabbbccc"
  101. if s != result {
  102. t.Fatalf("unexpected template value %q. Expected %q", s, result)
  103. }
  104. }
  105. func TestLongDelimiter(t *testing.T) {
  106. template := "foo{{{foo}}}bar"
  107. tpl := New(template, "{{{", "}}}")
  108. s := tpl.ExecuteString(map[string]interface{}{"foo": "111", "aaa": "bbb"})
  109. result := "foo111bar"
  110. if s != result {
  111. t.Fatalf("unexpected template value %q. Expected %q", s, result)
  112. }
  113. }
  114. func TestIdenticalDelimiter(t *testing.T) {
  115. template := "foo@foo@foo@aaa@"
  116. tpl := New(template, "@", "@")
  117. s := tpl.ExecuteString(map[string]interface{}{"foo": "111", "aaa": "bbb"})
  118. result := "foo111foobbb"
  119. if s != result {
  120. t.Fatalf("unexpected template value %q. Expected %q", s, result)
  121. }
  122. }
  123. func TestDlimitersWithDistinctSize(t *testing.T) {
  124. template := "foo<?phpaaa?>bar<?phpzzz?>"
  125. tpl := New(template, "<?php", "?>")
  126. s := tpl.ExecuteString(map[string]interface{}{"zzz": "111", "aaa": "bbb"})
  127. result := "foobbbbar111"
  128. if s != result {
  129. t.Fatalf("unexpected template value %q. Expected %q", s, result)
  130. }
  131. }
  132. func TestEmptyValue(t *testing.T) {
  133. template := "foobar[foo]"
  134. tpl := New(template, "[", "]")
  135. s := tpl.ExecuteString(map[string]interface{}{"foo": "", "aaa": "bbb"})
  136. result := "foobar"
  137. if s != result {
  138. t.Fatalf("unexpected template value %q. Expected %q", s, result)
  139. }
  140. }
  141. func TestNoValue(t *testing.T) {
  142. template := "foobar[foo]x[aaa]"
  143. tpl := New(template, "[", "]")
  144. s := tpl.ExecuteString(map[string]interface{}{"aaa": "bbb"})
  145. result := "foobarxbbb"
  146. if s != result {
  147. t.Fatalf("unexpected template value %q. Expected %q", s, result)
  148. }
  149. }
  150. func TestNoEndDelimiter(t *testing.T) {
  151. template := "foobar[foo"
  152. _, err := NewTemplate(template, "[", "]")
  153. if err == nil {
  154. t.Fatalf("expected non-nil error. got nil")
  155. }
  156. expectPanic(t, func() { New(template, "[", "]") })
  157. }
  158. func TestUnsupportedValue(t *testing.T) {
  159. template := "foobar[foo]"
  160. tpl := New(template, "[", "]")
  161. expectPanic(t, func() {
  162. tpl.ExecuteString(map[string]interface{}{"foo": 123, "aaa": "bbb"})
  163. })
  164. }
  165. func TestMixedValues(t *testing.T) {
  166. template := "foo[foo]bar[bar]baz[baz]"
  167. tpl := New(template, "[", "]")
  168. s := tpl.ExecuteString(map[string]interface{}{
  169. "foo": "111",
  170. "bar": []byte("bbb"),
  171. "baz": TagFunc(func(w io.Writer, tag string) (int, error) { return w.Write([]byte(tag)) }),
  172. })
  173. result := "foo111barbbbbazbaz"
  174. if s != result {
  175. t.Fatalf("unexpected template value %q. Expected %q", s, result)
  176. }
  177. }
  178. func TestExecuteFunc(t *testing.T) {
  179. testExecuteFunc(t, "", "")
  180. testExecuteFunc(t, "a", "a")
  181. testExecuteFunc(t, "abc", "abc")
  182. testExecuteFunc(t, "{foo}", "xxxx")
  183. testExecuteFunc(t, "a{foo}", "axxxx")
  184. testExecuteFunc(t, "{foo}a", "xxxxa")
  185. testExecuteFunc(t, "a{foo}bc", "axxxxbc")
  186. testExecuteFunc(t, "{foo}{foo}", "xxxxxxxx")
  187. testExecuteFunc(t, "{foo}bar{foo}", "xxxxbarxxxx")
  188. // unclosed tag
  189. testExecuteFunc(t, "{unclosed", "{unclosed")
  190. testExecuteFunc(t, "{{unclosed", "{{unclosed")
  191. testExecuteFunc(t, "{un{closed", "{un{closed")
  192. // test unknown tag
  193. testExecuteFunc(t, "{unknown}", "zz")
  194. testExecuteFunc(t, "{foo}q{unexpected}{missing}bar{foo}", "xxxxqzzzzbarxxxx")
  195. }
  196. func testExecuteFunc(t *testing.T, template, expectedOutput string) {
  197. var bb bytes.Buffer
  198. ExecuteFunc(template, "{", "}", &bb, func(w io.Writer, tag string) (int, error) {
  199. if tag == "foo" {
  200. return w.Write([]byte("xxxx"))
  201. }
  202. return w.Write([]byte("zz"))
  203. })
  204. output := string(bb.Bytes())
  205. if output != expectedOutput {
  206. t.Fatalf("unexpected output for template=%q: %q. Expected %q", template, output, expectedOutput)
  207. }
  208. }
  209. func TestExecute(t *testing.T) {
  210. testExecute(t, "", "")
  211. testExecute(t, "a", "a")
  212. testExecute(t, "abc", "abc")
  213. testExecute(t, "{foo}", "xxxx")
  214. testExecute(t, "a{foo}", "axxxx")
  215. testExecute(t, "{foo}a", "xxxxa")
  216. testExecute(t, "a{foo}bc", "axxxxbc")
  217. testExecute(t, "{foo}{foo}", "xxxxxxxx")
  218. testExecute(t, "{foo}bar{foo}", "xxxxbarxxxx")
  219. // unclosed tag
  220. testExecute(t, "{unclosed", "{unclosed")
  221. testExecute(t, "{{unclosed", "{{unclosed")
  222. testExecute(t, "{un{closed", "{un{closed")
  223. // test unknown tag
  224. testExecute(t, "{unknown}", "")
  225. testExecute(t, "{foo}q{unexpected}{missing}bar{foo}", "xxxxqbarxxxx")
  226. }
  227. func testExecute(t *testing.T, template, expectedOutput string) {
  228. var bb bytes.Buffer
  229. Execute(template, "{", "}", &bb, map[string]interface{}{"foo": "xxxx"})
  230. output := string(bb.Bytes())
  231. if output != expectedOutput {
  232. t.Fatalf("unexpected output for template=%q: %q. Expected %q", template, output, expectedOutput)
  233. }
  234. }
  235. func TestExecuteString(t *testing.T) {
  236. testExecuteString(t, "", "")
  237. testExecuteString(t, "a", "a")
  238. testExecuteString(t, "abc", "abc")
  239. testExecuteString(t, "{foo}", "xxxx")
  240. testExecuteString(t, "a{foo}", "axxxx")
  241. testExecuteString(t, "{foo}a", "xxxxa")
  242. testExecuteString(t, "a{foo}bc", "axxxxbc")
  243. testExecuteString(t, "{foo}{foo}", "xxxxxxxx")
  244. testExecuteString(t, "{foo}bar{foo}", "xxxxbarxxxx")
  245. // unclosed tag
  246. testExecuteString(t, "{unclosed", "{unclosed")
  247. testExecuteString(t, "{{unclosed", "{{unclosed")
  248. testExecuteString(t, "{un{closed", "{un{closed")
  249. // test unknown tag
  250. testExecuteString(t, "{unknown}", "")
  251. testExecuteString(t, "{foo}q{unexpected}{missing}bar{foo}", "xxxxqbarxxxx")
  252. }
  253. func testExecuteString(t *testing.T, template, expectedOutput string) {
  254. output := ExecuteString(template, "{", "}", map[string]interface{}{"foo": "xxxx"})
  255. if output != expectedOutput {
  256. t.Fatalf("unexpected output for template=%q: %q. Expected %q", template, output, expectedOutput)
  257. }
  258. }
  259. func expectPanic(t *testing.T, f func()) {
  260. defer func() {
  261. if r := recover(); r == nil {
  262. t.Fatalf("missing panic")
  263. }
  264. }()
  265. f()
  266. }
  267. func TestExecuteFuncStringWithErr(t *testing.T) {
  268. var expectErr = errors.New("test111")
  269. result, err := ExecuteFuncStringWithErr(`{a} is {b}'s best friend`, "{", "}", func(w io.Writer, tag string) (int, error) {
  270. if tag == "a" {
  271. return w.Write([]byte("Alice"))
  272. }
  273. return 0, expectErr
  274. })
  275. if err != expectErr {
  276. t.Fatalf("error must be the same as the error returned from f, expect: %s, actual: %s", expectErr, err)
  277. }
  278. if result != "" {
  279. t.Fatalf("result should be an empty string if error occurred")
  280. }
  281. result, err = ExecuteFuncStringWithErr(`{a} is {b}'s best friend`, "{", "}", func(w io.Writer, tag string) (int, error) {
  282. if tag == "a" {
  283. return w.Write([]byte("Alice"))
  284. }
  285. return w.Write([]byte("Bob"))
  286. })
  287. if err != nil {
  288. t.Fatalf("should success but found err: %s", err)
  289. }
  290. if result != "Alice is Bob's best friend" {
  291. t.Fatalf("expect: %s, but: %s", "Alice is Bob's best friend", result)
  292. }
  293. }
  294. func TestTpl_ExecuteFuncStringWithErr(t *testing.T) {
  295. var expectErr = errors.New("test111")
  296. tpl, err := NewTemplate(`{a} is {b}'s best friend`, "{", "}")
  297. if err != nil {
  298. t.Fatalf("should success, but found err: %s", err)
  299. }
  300. result, err := tpl.ExecuteFuncStringWithErr(func(w io.Writer, tag string) (int, error) {
  301. if tag == "a" {
  302. return w.Write([]byte("Alice"))
  303. }
  304. return 0, expectErr
  305. })
  306. if err != expectErr {
  307. t.Fatalf("error must be the same as the error returned from f, expect: %s, actual: %s", expectErr, err)
  308. }
  309. if result != "" {
  310. t.Fatalf("result should be an empty string if error occurred")
  311. }
  312. result, err = tpl.ExecuteFuncStringWithErr(func(w io.Writer, tag string) (int, error) {
  313. if tag == "a" {
  314. return w.Write([]byte("Alice"))
  315. }
  316. return w.Write([]byte("Bob"))
  317. })
  318. if err != nil {
  319. t.Fatalf("should success but found err: %s", err)
  320. }
  321. if result != "Alice is Bob's best friend" {
  322. t.Fatalf("expect: %s, but: %s", "Alice is Bob's best friend", result)
  323. }
  324. }