line_test.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. package door
  2. import (
  3. "bytes"
  4. "fmt"
  5. "testing"
  6. "unicode"
  7. )
  8. func TestLine(t *testing.T) {
  9. var textBuff *bytes.Buffer = &bytes.Buffer{}
  10. textBuff.WriteString("Test Me")
  11. var line *Line = &Line{Text: textBuff}
  12. var output string = string(line.Output())
  13. var expect string = string("Test Me")
  14. if output != expect {
  15. t.Errorf("Line: Expected %#v, got %#v", expect, output)
  16. }
  17. if line.Update() {
  18. t.Error("Line: No updater, should return false")
  19. }
  20. line.DefaultColor = Color([]int{0})
  21. line.Width = 8
  22. output = string(line.Output())
  23. expect = "\x1b[0mTest Me "
  24. if output != expect {
  25. t.Errorf("Line: Expected %#v, got %#v", expect, output)
  26. }
  27. // leave the default color, it is ignored when there's a render function
  28. // line.DefaultColor = ""
  29. line.RenderF = RenderBlueYellow
  30. output = string(line.Output())
  31. var blue string = ColorText("BOLD BLUE")
  32. var yellow string = ColorText("BOLD YELLOW")
  33. expect = blue + "T" + yellow + "est " + blue + "M" + yellow + "e "
  34. if output != expect {
  35. t.Errorf("Line: Expected %#v, got %#v", expect, output)
  36. }
  37. }
  38. func TestLineUpdate(t *testing.T) {
  39. var counter int = 0
  40. uf := func(u *bytes.Buffer) {
  41. u.Reset()
  42. fmt.Fprintf(u, "Count: %d", counter)
  43. }
  44. var line *Line = &Line{UpdateF: uf}
  45. line.Update()
  46. var output string = string(line.Output())
  47. var expect string = "Count: 0"
  48. if output != expect {
  49. t.Errorf("LineUpdate: Expected %#v, got %#v", expect, output)
  50. }
  51. if line.Update() {
  52. t.Error("Unexpected Update: should have returned false. (no change)")
  53. }
  54. counter++
  55. if !line.Update() {
  56. t.Error("Missing Update: value was changed, Text should have changed")
  57. }
  58. output = string(line.Output())
  59. expect = "Count: 1"
  60. if output != expect {
  61. t.Errorf("LineUpdate: Expected %#v, got %#v", expect, output)
  62. }
  63. }
  64. func TestLineUnicode(t *testing.T) {
  65. Unicode = true
  66. // code point > FFFF, use \U00000000 (not \u).
  67. var lineBuff *bytes.Buffer = &bytes.Buffer{}
  68. lineBuff.WriteString("Howdy \U0001f920")
  69. var line *Line = &Line{Text: lineBuff}
  70. var output []byte = line.Output()
  71. var expect []byte = []byte("Howdy 🤠")
  72. if bytes.Compare(output, expect) != 0 {
  73. t.Errorf("LineUnicode: Expected %s, got %s", expect, output)
  74. }
  75. if StringLen(expect) != 8 {
  76. t.Errorf("LineUnicode Strlen: Expected 8, got %d", StringLen(expect))
  77. }
  78. // 🤠 = 2 chars.
  79. line.Width = 9
  80. output = line.Output()
  81. expect = []byte("Howdy 🤠 ")
  82. if bytes.Compare(output, expect) != 0 {
  83. t.Errorf("LineUnicode: Expected %#v, got %#v", expect, output)
  84. }
  85. }
  86. func TestLineCP437(t *testing.T) {
  87. Unicode = false
  88. var tests []string = []string{"\xdb TEXT \xdb",
  89. "\xf1 F1", "\xf2 F2", "\xf3 F3"}
  90. for _, test := range tests {
  91. var lineBuff *bytes.Buffer = &bytes.Buffer{}
  92. lineBuff.WriteString(test)
  93. var line *Line = &Line{Text: lineBuff}
  94. var output string = string(line.Output())
  95. var expect string = test
  96. if output != expect {
  97. t.Errorf("LineCP437: Expected %#v, got %#v", expect, output)
  98. }
  99. }
  100. }
  101. // Benchmarks for profiling
  102. // go test -bench=BenchmarkLine -benchmem -memprofile memory.out -cpuprofile cpu.out
  103. // go tool pprof memory.out
  104. // go tool pprof cpu.out
  105. func BenchmarkLine(b *testing.B) {
  106. Unicode = false
  107. for n := 0; n < b.N; n++ {
  108. var lineBuff *bytes.Buffer = &bytes.Buffer{}
  109. fmt.Fprintf(lineBuff, "Line %d of %d", n, b.N)
  110. // lineBuff.WriteString(fmt.Sprintf("Line %d of %d", n, b.N))
  111. var line *Line = &Line{Text: lineBuff}
  112. line.Output()
  113. }
  114. }
  115. func BenchmarkLineColor(b *testing.B) {
  116. Unicode = false
  117. color := ColorText("BRI WHI ON BLUE")
  118. for n := 0; n < b.N; n++ {
  119. var lineBuff *bytes.Buffer = &bytes.Buffer{}
  120. fmt.Fprintf(lineBuff, "Line %d of %d", n, b.N)
  121. // lineBuff.WriteString(fmt.Sprintf("Line %d of %d", n, b.N))
  122. var line *Line = &Line{Text: lineBuff, DefaultColor: color}
  123. line.Output()
  124. }
  125. }
  126. func BenchmarkLineColorUnicode(b *testing.B) {
  127. Unicode = true
  128. color := ColorText("BRI WHI ON BLUE")
  129. for n := 0; n < b.N; n++ {
  130. var lineBuff *bytes.Buffer = &bytes.Buffer{}
  131. fmt.Fprintf(lineBuff, "Line %d of %d", n, b.N)
  132. // lineBuff.WriteString(fmt.Sprintf("Line %d of %d", n, b.N))
  133. var line *Line = &Line{Text: lineBuff, DefaultColor: color}
  134. line.Output()
  135. }
  136. }
  137. // Using RenderUppercase vs. RenderBlueYellow
  138. // BenchmarkLineRender-4 739462 1709 ns/op 376 B/op 13 allocs/op
  139. // BenchmarkLineRender-4 862102 1434 ns/op 648 B/op 9 allocs/op
  140. /*
  141. // This actually made BenchmarkLineUpdate worse.
  142. func printd(value int64, write io.Writer) {
  143. var buffer [32]byte
  144. var pos int
  145. if value == 0 {
  146. write.Write([]byte{'0'})
  147. return
  148. }
  149. for value > 0 {
  150. buffer[pos] = byte(int64('0') + value%10)
  151. pos++
  152. value = value / 10
  153. }
  154. for pos != 0 {
  155. pos--
  156. write.Write(buffer[pos : pos+1])
  157. }
  158. }
  159. */
  160. func BenchmarkLineUpdate(b *testing.B) {
  161. Unicode = false
  162. var line *Line = &Line{}
  163. var n int
  164. line.UpdateF = func(u *bytes.Buffer) {
  165. u.Reset()
  166. /*
  167. u.WriteString("Line ")
  168. printd(int64(n), u)
  169. u.WriteString(" of ")
  170. printd(int64(b.N), u)
  171. */
  172. fmt.Fprintf(u, "Line %d of %d", n, b.N)
  173. }
  174. line.Update()
  175. for n = 0; n < b.N; n++ {
  176. line.Update()
  177. line.Output()
  178. }
  179. }
  180. func BenchmarkLineRender(b *testing.B) {
  181. Unicode = false
  182. var rf ColorRender = RenderUppercase("RED", "GREEN")
  183. var line *Line = NewLine("ThIs Is CrAzY TeXt HeRe")
  184. line.RenderF = rf
  185. var n int
  186. for n = 0; n < b.N; n++ {
  187. line.Output()
  188. }
  189. }
  190. // Benchmarks / profiling
  191. // BenchmarkLineColor-4 2868162 403.9 ns/op 8 B/op 0 allocs/op
  192. // BenchmarkLineColor-4 2944704 400.0 ns/op 8 B/op 0 allocs/op
  193. // No change making Color strings to []byte. (reverted change)
  194. func BenchmarkLineRenderUpdate(b *testing.B) {
  195. var Up = ColorText("BLUE")
  196. var Down = ColorText("BOLD BLUE")
  197. var Num = ColorText("BRI GREEN")
  198. var Sym = ColorText("CYAN")
  199. var render = func(output *bytes.Buffer, text []byte) {
  200. output.Reset()
  201. var last *string
  202. // var r Render = Render{Line: text}
  203. for _, letter := range text {
  204. if unicode.IsUpper(rune(letter)) {
  205. if last != &Up {
  206. output.WriteString(Up)
  207. last = &Up
  208. }
  209. // r.Append(Up, 1)
  210. } else if unicode.IsLower(rune(letter)) {
  211. if last != &Down {
  212. output.WriteString(Down)
  213. last = &Down
  214. }
  215. // r.Append(Down, 1)
  216. } else if unicode.IsDigit(rune(letter)) {
  217. if last != &Num {
  218. output.WriteString(Num)
  219. last = &Num
  220. }
  221. // r.Append(Num, 1)
  222. } else {
  223. if last != &Sym {
  224. output.WriteString(Sym)
  225. last = &Sym
  226. }
  227. //r.Append(Sym, 1)
  228. }
  229. output.WriteByte(letter)
  230. // output.WriteString(string(letter))
  231. }
  232. // return output.Bytes()
  233. // return r.Result
  234. }
  235. var up int
  236. var updater = func(u *bytes.Buffer) {
  237. u.Reset()
  238. fmt.Fprintf(u, "The Value: %d", up)
  239. // u.WriteString("The Value: ")
  240. // u.WriteString(strconv.Itoa(up))
  241. up++
  242. // return fmt.Sprintf("The Value: %d", up)
  243. }
  244. var line *Line = &Line{UpdateF: updater,
  245. RenderF: render,
  246. Width: 18}
  247. for i := 0; i < b.N; i++ {
  248. line.Update()
  249. line.Output()
  250. }
  251. }