Files

150 lines
3.6 KiB
Go

package code
import (
"bytes"
"math/rand"
"testing"
"time"
"aego/editor/core/code/buffer"
"aego/editor/core/code/lines"
"aego/editor/core/code/search"
)
func TestTable(t *testing.T) {
b := buffer.New([]byte("hello world"))
b.Insert(5, []byte(","))
b.Delete(0, 1)
b.Insert(b.Len(), []byte("!"))
b.Insert(b.Len(), []byte("?"))
if got := string(b.Bytes()); got != "ello, world!?" {
t.Fatalf("got %q", got)
}
if got := string(b.Slice(2, 3, nil)); got != "lo," {
t.Fatalf("slice %q", got)
}
}
func TestRandomEditsKeepIndex(t *testing.T) {
rnd := rand.New(rand.NewSource(1))
ref := []byte("a\nbb\n\nccc\n")
b := buffer.New(ref)
idx := lines.New(ref)
alphabet := []byte("xy\n\t")
for i := 0; i < 3000; i++ {
off := rnd.Intn(len(ref) + 1)
n := 0
if off < len(ref) && rnd.Intn(2) == 0 {
n = rnd.Intn(min(4, len(ref)-off) + 1)
}
ins := make([]byte, rnd.Intn(4))
for k := range ins {
ins[k] = alphabet[rnd.Intn(len(alphabet))]
}
ref = append(append(append([]byte(nil), ref[:off]...), ins...), ref[off+n:]...)
b.Delete(off, n)
b.Insert(off, ins)
idx.Edit(off, n, ins)
}
if !bytes.Equal(b.Bytes(), ref) {
t.Fatal("piece table diverged")
}
want := lines.New(ref)
if idx.Count() != want.Count() {
t.Fatalf("lines %d, want %d", idx.Count(), want.Count())
}
for l := 0; l < want.Count(); l++ {
if idx.Offset(l) != want.Offset(l) || idx.End(l) != want.End(l) {
t.Fatalf("line %d differs", l)
}
}
}
func clocked(src string) (*Doc, *time.Time) {
d := New([]byte(src))
now := time.Unix(0, 0)
d.Now = func() time.Time { return now }
return d, &now
}
func TestUndoGroups(t *testing.T) {
d, now := clocked("")
for _, s := range []string{"a", "b", "c"} {
d.Type(s)
*now = now.Add(100 * time.Millisecond)
}
*now = now.Add(time.Second)
d.Type("d")
d.Undo()
if got := string(d.Bytes()); got != "abc" {
t.Fatalf("after first undo %q", got)
}
d.Undo()
if got := string(d.Bytes()); got != "" || d.Dirty() {
t.Fatalf("after second undo %q dirty=%v", got, d.Dirty())
}
d.Redo()
if got := string(d.Bytes()); got != "abc" {
t.Fatalf("redo %q", got)
}
}
func TestUTF8Cursor(t *testing.T) {
d := New([]byte("привет мир\nxy"))
d.SetCursor(0, false)
d.Move(Right, true, false)
if l, c := d.LineCol(d.Cursor()); l != 0 || c != 6 {
t.Fatalf("word right lands at %d:%d", l, c)
}
d.Move(Down, false, false)
if l, c := d.LineCol(d.Cursor()); l != 1 || c != 2 {
t.Fatalf("down lands at %d:%d", l, c)
}
d.Move(Up, false, false)
if _, c := d.LineCol(d.Cursor()); c != 6 {
t.Fatalf("goal column lost: %d", c)
}
d.Delete(Left, false)
if got := string(d.Bytes()); got != "приве мир\nxy" {
t.Fatalf("delete %q", got)
}
}
func TestIndentCommentNewline(t *testing.T) {
d := New([]byte("a\nb\nc"))
d.Select(0, d.Len())
d.Indent()
if got := string(d.Bytes()); got != "\ta\n\tb\n\tc" {
t.Fatalf("indent %q", got)
}
d.Unindent()
d.ToggleComment()
if got := string(d.Bytes()); got != "// a\n// b\n// c" {
t.Fatalf("comment %q", got)
}
d.ToggleComment()
if got := string(d.Bytes()); got != "a\nb\nc" {
t.Fatalf("uncomment %q", got)
}
e := New([]byte("\tfunc A() {}"))
e.SetCursor(len("\tfunc A() {"), false)
e.Newline()
if got := string(e.Bytes()); got != "\tfunc A() {\n\t\t\n\t}" {
t.Fatalf("newline %q", got)
}
}
func TestSearchReplace(t *testing.T) {
d := New([]byte("Foo foo food"))
if n := d.ReplaceAll("foo", "bar", search.Options{Word: true}); n != 2 {
t.Fatalf("replaced %d", n)
}
if got := string(d.Bytes()); got != "bar bar food" {
t.Fatalf("got %q", got)
}
d.Undo()
if got := string(d.Bytes()); got != "Foo foo food" {
t.Fatalf("undo %q", got)
}
}