NAME=t/undoredo
FILE=malloc://1024
CMDS=<<EOF
echo No seeks.
sh* ; %v $$
echo

echo But try undo/redo.
shu
shr
sh*
shr
shr
shu
shu
shu
shr
sh*
echo

echo First seeks.
s 0x10 ; sh* ; %v $$
s 0x20 ; sh* ; %v $$
s 0x30 ; sh* ; %v $$
s 0x40 ; sh* ; %v $$
echo

echo Undo all seeks (and some more).
shu ; sh* ; %v $$ ; echo
shu ; sh* ; %v $$ ; echo
shu ; sh* ; %v $$ ; echo
shu ; sh* ; %v $$ ; echo
# Test if more undos break something.
shu ; sh* ; %v $$ ; echo
shu ; sh* ; %v $$ ; echo

echo Then redo them (and some more).
shr ; sh* ; %v $$ ; echo
shr ; sh* ; %v $$ ; echo
shr ; sh* ; %v $$ ; echo
shr ; sh* ; %v $$ ; echo
# Test if more undos break something.
shr ; sh* ; %v $$ ; echo
shr ; sh* ; %v $$ ; echo

echo Undo some seeks and then seek somewhere else.
shu ; shu
sh* ; %v $$ ; echo
s 0x50
sh* ; %v $$ ; echo
# Redo now does nothing.
shr ; shr ; shr
sh* ; %v $$ ; echo

echo Undo all seeks again and perform a single seek with undo/redo.
shu ; shu ; shu
sh* ; %v $$ ; echo
s 0x100
sh* ; %v $$ ; echo
shu ; shr
sh* ; %v $$ ; echo
EOF
EXPECT=<<EOF
No seeks.
# Current seek @ 0x0
0x0

But try undo/redo.
# Current seek @ 0x0
# Current seek @ 0x0

First seeks.
f undo_0 @ 0x0
# Current seek @ 0x10
0x10
f undo_1 @ 0x0
f undo_0 @ 0x10
# Current seek @ 0x20
0x20
f undo_2 @ 0x0
f undo_1 @ 0x10
f undo_0 @ 0x20
# Current seek @ 0x30
0x30
f undo_3 @ 0x0
f undo_2 @ 0x10
f undo_1 @ 0x20
f undo_0 @ 0x30
# Current seek @ 0x40
0x40

Undo all seeks (and some more).
f undo_2 @ 0x0
f undo_1 @ 0x10
f undo_0 @ 0x20
# Current seek @ 0x30
f redo_0 @ 0x40
0x30

f undo_1 @ 0x0
f undo_0 @ 0x10
# Current seek @ 0x20
f redo_0 @ 0x30
f redo_1 @ 0x40
0x20

f undo_0 @ 0x0
# Current seek @ 0x10
f redo_0 @ 0x20
f redo_1 @ 0x30
f redo_2 @ 0x40
0x10

# Current seek @ 0x0
f redo_0 @ 0x10
f redo_1 @ 0x20
f redo_2 @ 0x30
f redo_3 @ 0x40
0x0

# Current seek @ 0x0
f redo_0 @ 0x10
f redo_1 @ 0x20
f redo_2 @ 0x30
f redo_3 @ 0x40
0x0

# Current seek @ 0x0
f redo_0 @ 0x10
f redo_1 @ 0x20
f redo_2 @ 0x30
f redo_3 @ 0x40
0x0

Then redo them (and some more).
f undo_0 @ 0x0
# Current seek @ 0x10
f redo_0 @ 0x20
f redo_1 @ 0x30
f redo_2 @ 0x40
0x10

f undo_1 @ 0x0
f undo_0 @ 0x10
# Current seek @ 0x20
f redo_0 @ 0x30
f redo_1 @ 0x40
0x20

f undo_2 @ 0x0
f undo_1 @ 0x10
f undo_0 @ 0x20
# Current seek @ 0x30
f redo_0 @ 0x40
0x30

f undo_3 @ 0x0
f undo_2 @ 0x10
f undo_1 @ 0x20
f undo_0 @ 0x30
# Current seek @ 0x40
0x40

f undo_3 @ 0x0
f undo_2 @ 0x10
f undo_1 @ 0x20
f undo_0 @ 0x30
# Current seek @ 0x40
0x40

f undo_3 @ 0x0
f undo_2 @ 0x10
f undo_1 @ 0x20
f undo_0 @ 0x30
# Current seek @ 0x40
0x40

Undo some seeks and then seek somewhere else.
f undo_1 @ 0x0
f undo_0 @ 0x10
# Current seek @ 0x20
f redo_0 @ 0x30
f redo_1 @ 0x40
0x20

f undo_2 @ 0x0
f undo_1 @ 0x10
f undo_0 @ 0x20
# Current seek @ 0x50
0x50

f undo_2 @ 0x0
f undo_1 @ 0x10
f undo_0 @ 0x20
# Current seek @ 0x50
0x50

Undo all seeks again and perform a single seek with undo/redo.
# Current seek @ 0x0
f redo_0 @ 0x10
f redo_1 @ 0x20
f redo_2 @ 0x50
0x0

f undo_0 @ 0x0
# Current seek @ 0x100
0x100

f undo_0 @ 0x0
# Current seek @ 0x100
0x100

EOF
RUN

NAME=basic json
FILE=malloc://1024
CMDS=<<EOF
shj
sd +10
shj
sd +10
shu
shj
shu
shj
echo undo at the start of list
shu
shj
echo redo to the end
shr; shr
shj
echo one more past the end
shr
shj
EOF
EXPECT=<<EOF
[{"offset":0,"cursor":0,"current":true}]
[{"offset":0,"cursor":0,"current":false},{"offset":10,"cursor":0,"current":true}]
[{"offset":0,"cursor":0,"current":false},{"offset":10,"cursor":0,"current":true},{"offset":20,"cursor":0,"current":false}]
[{"offset":0,"cursor":0,"current":true},{"offset":10,"cursor":0,"current":false},{"offset":20,"cursor":0,"current":false}]
undo at the start of list
[{"offset":0,"cursor":0,"current":true},{"offset":10,"cursor":0,"current":false},{"offset":20,"cursor":0,"current":false}]
redo to the end
[{"offset":0,"cursor":0,"current":false},{"offset":10,"cursor":0,"current":false},{"offset":20,"cursor":0,"current":true}]
one more past the end
[{"offset":0,"cursor":0,"current":false},{"offset":10,"cursor":0,"current":false},{"offset":20,"cursor":0,"current":true}]
EOF
RUN

NAME=uninitialized bug
FILE=malloc://1024
CMDS=<<EOF
sd +10
echo should produce two identical results
sd +1
shj
shu
sd +1
shj
echo 0 0, or 22 23 but not 0 22
sd +10
sd +1
shj
shu
sd +2
shj
EOF
EXPECT=<<EOF
should produce two identical results
[{"offset":0,"cursor":0,"current":false},{"offset":10,"cursor":0,"current":false},{"offset":11,"cursor":0,"current":true}]
[{"offset":0,"cursor":0,"current":false},{"offset":10,"cursor":0,"current":false},{"offset":11,"cursor":0,"current":true}]
0 0, or 22 23 but not 0 22
[{"offset":0,"cursor":0,"current":false},{"offset":10,"cursor":0,"current":false},{"offset":11,"cursor":0,"current":false},{"offset":21,"cursor":0,"current":false},{"offset":22,"cursor":0,"current":true}]
[{"offset":0,"cursor":0,"current":false},{"offset":10,"cursor":0,"current":false},{"offset":11,"cursor":0,"current":false},{"offset":21,"cursor":0,"current":false},{"offset":23,"cursor":0,"current":true}]
EOF
RUN

NAME=duplicate push
FILE=malloc://1024
CMDS=<<EOF
s 0x0
s 0x0
s 0x1
s 0x2
# shouldn't contain multiple 0 at the start
shj
# regression test for deduplication not working on buffer edge
60sd +1
s 0x0
s 0x0
s 0x01
s 0x02
sh*~:-6..
EOF
EXPECT=<<EOF
[{"offset":0,"cursor":0,"current":false},{"offset":1,"cursor":0,"current":false},{"offset":2,"cursor":0,"current":true}]
f undo_4 @ 0x3c
f undo_3 @ 0x3d
f undo_2 @ 0x3e
f undo_1 @ 0x0
f undo_0 @ 0x1
# Current seek @ 0x2
EOF
RUN