cview/textview_test.go

324 lines
6.9 KiB
Go

package cview
import (
"bytes"
"fmt"
"strings"
"testing"
)
const (
// 512 bytes
randomDataSize = 512
// Write randomData 64 times (32768 bytes) before appending
appendSetupWriteCount = 64
)
var (
randomData = generateRandomData()
textViewTestCases = generateTestCases()
)
type textViewTestCase struct {
app bool
color bool
region bool
scroll bool
wrap bool
wordwrap bool
}
func (c *textViewTestCase) String() string {
return fmt.Sprintf("Append=%c/Color=%c/Region=%c/Scroll=%c/Wrap=%c/WordWrap=%c", cl(c.app), cl(c.color), cl(c.region), cl(c.scroll), cl(c.wrap), cl(c.wordwrap))
}
func TestTextViewWrite(t *testing.T) {
t.Parallel()
for _, c := range textViewTestCases {
c := c // Capture
t.Run(c.String(), func(t *testing.T) {
t.Parallel()
var (
tv = tvc(NewTextView(), c)
expectedData []byte
n int
err error
)
if c.app {
expectedData, err = prepareAppendTextView(tv)
if err != nil {
t.Errorf("failed to prepare append TextView: %s", err)
}
expectedData = append(expectedData, randomData...)
} else {
expectedData = randomData
}
n, err = tv.Write(randomData)
if err != nil {
t.Errorf("failed to write (successfully wrote %d) bytes: %s", n, err)
} else if n != randomDataSize {
t.Errorf("failed to write: expected to write %d bytes, wrote %d", randomDataSize, n)
}
contents := tv.GetText(false)
if len(contents) > 0 {
contents = contents[0 : len(contents)-1] // Remove extra newline
}
if len(contents) != len(expectedData) {
t.Errorf("failed to write: incorrect contents: expected %d bytes, got %d", len(contents), len(expectedData))
} else if !bytes.Equal([]byte(contents), expectedData) {
t.Errorf("failed to write: incorrect contents: values do not match")
}
tv.Clear()
})
}
}
func BenchmarkTextViewWrite(b *testing.B) {
for _, c := range textViewTestCases {
c := c // Capture
b.Run(c.String(), func(b *testing.B) {
var (
tv = tvc(NewTextView(), c)
n int
err error
)
if c.app {
_, err = prepareAppendTextView(tv)
if err != nil {
b.Errorf("failed to prepare append TextView: %s", err)
}
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
n, err = tv.Write(randomData)
if err != nil {
b.Errorf("failed to write (successfully wrote %d) bytes: %s", n, err)
} else if n != randomDataSize {
b.Errorf("failed to write: expected to write %d bytes, wrote %d", randomDataSize, n)
}
if !c.app {
b.StopTimer()
tv.Clear()
b.StartTimer()
}
}
})
}
}
func TestTextViewDraw(t *testing.T) {
t.Parallel()
for _, c := range textViewTestCases {
c := c // Capture
t.Run(c.String(), func(t *testing.T) {
t.Parallel()
tv := tvc(NewTextView(), c)
app, err := newTestApp(tv)
if err != nil {
t.Errorf("failed to initialize Application: %s", err)
}
if c.app {
_, err = prepareAppendTextView(tv)
if err != nil {
t.Errorf("failed to prepare append TextView: %s", err)
}
tv.Draw(app.screen)
}
n, err := tv.Write(randomData)
if err != nil {
t.Errorf("failed to write (successfully wrote %d) bytes: %s", n, err)
} else if n != randomDataSize {
t.Errorf("failed to write: expected to write %d bytes, wrote %d", randomDataSize, n)
}
tv.Draw(app.screen)
})
}
}
func BenchmarkTextViewDraw(b *testing.B) {
for _, c := range textViewTestCases {
c := c // Capture
b.Run(c.String(), func(b *testing.B) {
tv := tvc(NewTextView(), c)
app, err := newTestApp(tv)
if err != nil {
b.Errorf("failed to initialize Application: %s", err)
}
if c.app {
_, err = prepareAppendTextView(tv)
if err != nil {
b.Errorf("failed to prepare append TextView: %s", err)
}
tv.Draw(app.screen)
}
n, err := tv.Write(randomData)
if err != nil {
b.Errorf("failed to write (successfully wrote %d) bytes: %s", n, err)
} else if n != randomDataSize {
b.Errorf("failed to write: expected to write %d bytes, wrote %d", randomDataSize, n)
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
tv.Draw(app.screen)
}
})
}
}
func TestTextViewMaxLines(t *testing.T) {
tv := NewTextView()
// append 100 lines with no limit set:
for i := 0; i < 100; i++ {
_, err := tv.Write([]byte(fmt.Sprintf("L%d\n", i)))
if err != nil {
t.Errorf("failed to write to TextView: %s", err)
}
}
// retrieve the total text and see we have the 100 lines:
count := strings.Count(tv.GetText(true), "\n")
if count != 100 {
t.Errorf("expected 100 lines, got %d", count)
}
// now set the maximum lines to 20, this should clip the buffer:
tv.SetMaxLines(20)
// verify buffer was clipped:
count = len(strings.Split(tv.GetText(true), "\n"))
if count != 20 {
t.Errorf("expected 20 lines, got %d", count)
}
// append 100 more lines:
for i := 100; i < 200; i++ {
_, err := tv.Write([]byte(fmt.Sprintf("L%d\n", i)))
if err != nil {
t.Errorf("failed to write to TextView: %s", err)
}
}
// Sice max lines is set to 20, we should still get 20 lines:
txt := tv.GetText(true)
lines := strings.Split(txt, "\n")
count = len(lines)
if count != 20 {
t.Errorf("expected 20 lines, got %d", count)
}
// and those 20 lines should be the last ones:
if lines[0] != "L181" {
t.Errorf("expected to get L181, got %s", lines[0])
}
}
func generateTestCases() []*textViewTestCase {
var cases []*textViewTestCase
for i := 0; i < 2; i++ {
app := i == 1
for i := 0; i < 2; i++ {
color := i == 1
for i := 0; i < 2; i++ {
region := i == 1
for i := 0; i < 2; i++ {
scroll := i == 1
for i := 0; i < 2; i++ {
wrap := i == 1
for i := 0; i < 2; i++ {
wordwrap := i == 1
if !wrap && wordwrap {
continue // WordWrap requires Wrap
}
cases = append(cases, &textViewTestCase{app, color, region, scroll, wrap, wordwrap})
}
}
}
}
}
}
return cases
}
func generateRandomData() []byte {
var (
b bytes.Buffer
r = 33
)
for i := 0; i < randomDataSize; i++ {
if i%80 == 0 && i <= 160 {
b.WriteRune('\n')
} else if i%7 == 0 {
b.WriteRune(' ')
} else {
b.WriteRune(rune(r))
}
r++
if r == 127 {
r = 33
}
}
return b.Bytes()
}
func tvc(tv *TextView, c *textViewTestCase) *TextView {
return tv.SetDynamicColors(c.color).SetRegions(c.region).SetScrollable(c.scroll).SetWrap(c.wrap).SetWordWrap(c.wordwrap)
}
func cl(v bool) rune {
if v {
return 'T'
}
return 'F'
}
func prepareAppendTextView(t *TextView) ([]byte, error) {
var b []byte
for i := 0; i < appendSetupWriteCount; i++ {
b = append(b, randomData...)
n, err := t.Write(randomData)
if err != nil {
return nil, fmt.Errorf("failed to write (successfully wrote %d) bytes: %s", n, err)
} else if n != randomDataSize {
return nil, fmt.Errorf("failed to write: expected to write %d bytes, wrote %d", randomDataSize, n)
}
}
return b, nil
}