mirror of
https://github.com/zyedidia/micro.git
synced 2025-06-18 23:05:40 -04:00

Adding InitRuntimeFiles() to buffer_test.go has changed the behavior of this test: now it tests not just buffer editing per se, but also how well buffer editing works together with syntax highlighting (since InitRuntimeFiles() loads syntax files, and many of the test buffers match the json header pattern in the json.yaml syntax file, so they are "highlighted" as json). This revealed long existing races between buffer editing and syntax highlighting. Until we fix those races, temporarily disable InitRuntimeFiles() in this test.
326 lines
6.7 KiB
Go
326 lines
6.7 KiB
Go
package buffer
|
|
|
|
import (
|
|
"math/rand"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
lua "github.com/yuin/gopher-lua"
|
|
"github.com/zyedidia/micro/v2/internal/config"
|
|
ulua "github.com/zyedidia/micro/v2/internal/lua"
|
|
"github.com/zyedidia/micro/v2/internal/util"
|
|
)
|
|
|
|
type operation struct {
|
|
start Loc
|
|
end Loc
|
|
text []string
|
|
}
|
|
|
|
func init() {
|
|
ulua.L = lua.NewState()
|
|
// TODO: uncomment InitRuntimeFiles once we fix races between syntax
|
|
// highlighting and buffer editing.
|
|
// config.InitRuntimeFiles(false)
|
|
config.InitGlobalSettings()
|
|
config.GlobalSettings["backup"] = false
|
|
config.GlobalSettings["fastdirty"] = true
|
|
}
|
|
|
|
func check(t *testing.T, before []string, operations []operation, after []string) {
|
|
assert := assert.New(t)
|
|
|
|
b := NewBufferFromString(strings.Join(before, "\n"), "", BTDefault)
|
|
|
|
assert.NotEqual("", b.GetName())
|
|
assert.Equal(false, b.ExternallyModified())
|
|
assert.Equal(false, b.Modified())
|
|
assert.Equal(1, b.NumCursors())
|
|
|
|
checkText := func(lines []string) {
|
|
assert.Equal([]byte(strings.Join(lines, "\n")), b.Bytes())
|
|
assert.Equal(len(lines), b.LinesNum())
|
|
for i, s := range lines {
|
|
assert.Equal(s, b.Line(i))
|
|
assert.Equal([]byte(s), b.LineBytes(i))
|
|
}
|
|
}
|
|
|
|
checkText(before)
|
|
|
|
var cursors []*Cursor
|
|
|
|
for _, op := range operations {
|
|
cursor := NewCursor(b, op.start)
|
|
cursor.SetSelectionStart(op.start)
|
|
cursor.SetSelectionEnd(op.end)
|
|
b.AddCursor(cursor)
|
|
cursors = append(cursors, cursor)
|
|
}
|
|
|
|
assert.Equal(1+len(operations), b.NumCursors())
|
|
|
|
for i, op := range operations {
|
|
cursor := cursors[i]
|
|
b.SetCurCursor(cursor.Num)
|
|
cursor.DeleteSelection()
|
|
b.Insert(cursor.Loc, strings.Join(op.text, "\n"))
|
|
}
|
|
|
|
checkText(after)
|
|
|
|
// must have exactly two events per operation (delete and insert)
|
|
for range operations {
|
|
b.UndoOneEvent()
|
|
b.UndoOneEvent()
|
|
}
|
|
|
|
checkText(before)
|
|
|
|
for i, op := range operations {
|
|
cursor := cursors[i]
|
|
if op.start == op.end {
|
|
assert.Equal(op.start, cursor.Loc)
|
|
} else {
|
|
assert.Equal(op.start, cursor.CurSelection[0])
|
|
assert.Equal(op.end, cursor.CurSelection[1])
|
|
}
|
|
}
|
|
|
|
for range operations {
|
|
b.RedoOneEvent()
|
|
b.RedoOneEvent()
|
|
}
|
|
|
|
checkText(after)
|
|
|
|
b.Close()
|
|
}
|
|
|
|
const maxLineLength = 200
|
|
|
|
var alphabet = []rune(" abcdeäم📚")
|
|
|
|
func randomString(length int) string {
|
|
runes := make([]rune, length)
|
|
for i := range runes {
|
|
runes[i] = alphabet[rand.Intn(len(alphabet))]
|
|
}
|
|
return string(runes)
|
|
}
|
|
|
|
func randomText(nLines int) string {
|
|
lines := make([]string, nLines)
|
|
for i := range lines {
|
|
lines[i] = randomString(rand.Intn(maxLineLength + 1))
|
|
}
|
|
return strings.Join(lines, "\n")
|
|
}
|
|
|
|
func benchCreateAndClose(testingB *testing.B, nLines int) {
|
|
rand.Seed(int64(nLines))
|
|
|
|
text := randomText(nLines)
|
|
|
|
testingB.ResetTimer()
|
|
|
|
for i := 0; i < testingB.N; i++ {
|
|
b := NewBufferFromString(text, "", BTDefault)
|
|
b.Close()
|
|
}
|
|
}
|
|
|
|
func benchRead(testingB *testing.B, nLines int) {
|
|
rand.Seed(int64(nLines))
|
|
|
|
b := NewBufferFromString(randomText(nLines), "", BTDefault)
|
|
|
|
testingB.ResetTimer()
|
|
|
|
for i := 0; i < testingB.N; i++ {
|
|
b.Bytes()
|
|
for j := 0; j < b.LinesNum(); j++ {
|
|
b.Line(j)
|
|
b.LineBytes(j)
|
|
}
|
|
}
|
|
|
|
testingB.StopTimer()
|
|
|
|
b.Close()
|
|
}
|
|
|
|
func benchEdit(testingB *testing.B, nLines, nCursors int) {
|
|
rand.Seed(int64(nLines + nCursors))
|
|
|
|
b := NewBufferFromString(randomText(nLines), "", BTDefault)
|
|
|
|
regionSize := nLines / nCursors
|
|
|
|
operations := make([]operation, nCursors)
|
|
for i := range operations {
|
|
startLine := (i * regionSize) + rand.Intn(regionSize-5)
|
|
startColumn := rand.Intn(util.CharacterCountInString(b.Line(startLine)) + 1)
|
|
endLine := startLine + 1 + rand.Intn(5)
|
|
endColumn := rand.Intn(util.CharacterCountInString(b.Line(endLine)) + 1)
|
|
|
|
operations[i] = operation{
|
|
start: Loc{startColumn, startLine},
|
|
end: Loc{endColumn, endLine},
|
|
text: []string{randomText(2 + rand.Intn(4))},
|
|
}
|
|
}
|
|
|
|
testingB.ResetTimer()
|
|
|
|
for i := 0; i < testingB.N; i++ {
|
|
b.SetCursors([]*Cursor{})
|
|
|
|
var cursors []*Cursor
|
|
|
|
for _, op := range operations {
|
|
cursor := NewCursor(b, op.start)
|
|
cursor.SetSelectionStart(op.start)
|
|
cursor.SetSelectionEnd(op.end)
|
|
b.AddCursor(cursor)
|
|
cursors = append(cursors, cursor)
|
|
}
|
|
|
|
for j, op := range operations {
|
|
cursor := cursors[j]
|
|
b.SetCurCursor(cursor.Num)
|
|
cursor.DeleteSelection()
|
|
b.Insert(cursor.Loc, op.text[0])
|
|
}
|
|
|
|
for b.UndoStack.Peek() != nil {
|
|
b.UndoOneEvent()
|
|
}
|
|
}
|
|
|
|
testingB.StopTimer()
|
|
|
|
b.Close()
|
|
}
|
|
|
|
func BenchmarkCreateAndClose10Lines(b *testing.B) {
|
|
benchCreateAndClose(b, 10)
|
|
}
|
|
|
|
func BenchmarkCreateAndClose100Lines(b *testing.B) {
|
|
benchCreateAndClose(b, 100)
|
|
}
|
|
|
|
func BenchmarkCreateAndClose1000Lines(b *testing.B) {
|
|
benchCreateAndClose(b, 1000)
|
|
}
|
|
|
|
func BenchmarkCreateAndClose10000Lines(b *testing.B) {
|
|
benchCreateAndClose(b, 10000)
|
|
}
|
|
|
|
func BenchmarkCreateAndClose100000Lines(b *testing.B) {
|
|
benchCreateAndClose(b, 100000)
|
|
}
|
|
|
|
func BenchmarkCreateAndClose1000000Lines(b *testing.B) {
|
|
benchCreateAndClose(b, 1000000)
|
|
}
|
|
|
|
func BenchmarkRead10Lines(b *testing.B) {
|
|
benchRead(b, 10)
|
|
}
|
|
|
|
func BenchmarkRead100Lines(b *testing.B) {
|
|
benchRead(b, 100)
|
|
}
|
|
|
|
func BenchmarkRead1000Lines(b *testing.B) {
|
|
benchRead(b, 1000)
|
|
}
|
|
|
|
func BenchmarkRead10000Lines(b *testing.B) {
|
|
benchRead(b, 10000)
|
|
}
|
|
|
|
func BenchmarkRead100000Lines(b *testing.B) {
|
|
benchRead(b, 100000)
|
|
}
|
|
|
|
func BenchmarkRead1000000Lines(b *testing.B) {
|
|
benchRead(b, 1000000)
|
|
}
|
|
|
|
func BenchmarkEdit10Lines1Cursor(b *testing.B) {
|
|
benchEdit(b, 10, 1)
|
|
}
|
|
|
|
func BenchmarkEdit100Lines1Cursor(b *testing.B) {
|
|
benchEdit(b, 100, 1)
|
|
}
|
|
|
|
func BenchmarkEdit100Lines10Cursors(b *testing.B) {
|
|
benchEdit(b, 100, 10)
|
|
}
|
|
|
|
func BenchmarkEdit1000Lines1Cursor(b *testing.B) {
|
|
benchEdit(b, 1000, 1)
|
|
}
|
|
|
|
func BenchmarkEdit1000Lines10Cursors(b *testing.B) {
|
|
benchEdit(b, 1000, 10)
|
|
}
|
|
|
|
func BenchmarkEdit1000Lines100Cursors(b *testing.B) {
|
|
benchEdit(b, 1000, 100)
|
|
}
|
|
|
|
func BenchmarkEdit10000Lines1Cursor(b *testing.B) {
|
|
benchEdit(b, 10000, 1)
|
|
}
|
|
|
|
func BenchmarkEdit10000Lines10Cursors(b *testing.B) {
|
|
benchEdit(b, 10000, 10)
|
|
}
|
|
|
|
func BenchmarkEdit10000Lines100Cursors(b *testing.B) {
|
|
benchEdit(b, 10000, 100)
|
|
}
|
|
|
|
func BenchmarkEdit10000Lines1000Cursors(b *testing.B) {
|
|
benchEdit(b, 10000, 1000)
|
|
}
|
|
|
|
func BenchmarkEdit100000Lines1Cursor(b *testing.B) {
|
|
benchEdit(b, 100000, 1)
|
|
}
|
|
|
|
func BenchmarkEdit100000Lines10Cursors(b *testing.B) {
|
|
benchEdit(b, 100000, 10)
|
|
}
|
|
|
|
func BenchmarkEdit100000Lines100Cursors(b *testing.B) {
|
|
benchEdit(b, 100000, 100)
|
|
}
|
|
|
|
func BenchmarkEdit100000Lines1000Cursors(b *testing.B) {
|
|
benchEdit(b, 100000, 1000)
|
|
}
|
|
|
|
func BenchmarkEdit1000000Lines1Cursor(b *testing.B) {
|
|
benchEdit(b, 1000000, 1)
|
|
}
|
|
|
|
func BenchmarkEdit1000000Lines10Cursors(b *testing.B) {
|
|
benchEdit(b, 1000000, 10)
|
|
}
|
|
|
|
func BenchmarkEdit1000000Lines100Cursors(b *testing.B) {
|
|
benchEdit(b, 1000000, 100)
|
|
}
|
|
|
|
func BenchmarkEdit1000000Lines1000Cursors(b *testing.B) {
|
|
benchEdit(b, 1000000, 1000)
|
|
}
|