okami.mom/ultraviolet
git clone https://git.nkp.pet/okami.mom/ultraviolet
7bfbaab
main
1package uv 2 3import ( 4"io" 5"reflect" 6"strings" 7"testing" 8"time" 9) 10 11// Control strings split across reads, the way a large OSC 5522 clipboard 12// reply arrives over ssh. 13 14// stalledReader returns one chunk per Read, pausing before each like a slow 15// network link. 16type stalledReader struct { 17chunks []string 18pause time.Duration 19} 20 21func (r * stalledReader )Read (p []byte ) (int ,error ) { 22if len (r .chunks )== 0 { 23return 0 ,io .EOF 24 } 25time .Sleep (r .pause ) 26n := copy (p ,r .chunks [0 ]) 27r .chunks = r .chunks [1 :] 28return n ,nil 29} 30 31func TestDecodeWaitsForSplitStringTerminator (t * testing.T ) { 32for name ,seq := range map [string ]string { 33"osc" :"\x1b]5522;type=read:status=DATA;QUJD\x1b" , 34"apc" :"\x1b_Gi=1;OK\x1b" , 35"dcs" :"\x1bP1+r5463=31\x1b" , 36 } { 37t .Run (name ,func (t * testing.T ) { 38var d EventDecoder 39n ,ev := d .Decode ([]byte (seq )) 40if _ ,ok := ev .(UnknownEvent );! ok || n != len (seq ) { 41t .Fatalf ("Decode(%q) = %d, %T; want an incomplete UnknownEvent over the whole buffer" ,seq ,n ,ev ) 42 } 43 }) 44 } 45} 46 47func TestStreamEventsKeepsOscAcrossStalledReads (t * testing.T ) { 48payload := strings .Repeat ("QUJD" ,2000 ) 49osc := "\x1b]5522;type=read:status=DATA:id=x;" + payload + "\x1b\\" 50half := len (osc )/ 2 51chunks := []string { 52osc [:half ],// stall mid payload 53osc [half :len (osc )- 1 ],// stall between ESC and the backslash of ST 54osc [len (osc )- 1 :]+ "a" , 55 } 56events := testReadInputs (t ,& stalledReader {chunks :chunks ,pause :4 * DefaultEscTimeout }) 57want := []Event {UnknownOscEvent (osc ),KeyPressEvent {Code :'a' ,Text :"a" }} 58if ! reflect .DeepEqual (events ,want ) { 59t .Fatalf ("events = %#v\nwant %#v" ,events ,want ) 60 } 61} 62 63func TestStreamEventsFlushesStalledClipboardOscAfterItsTimeout (t * testing.T ) { 64saved := pendingClipboardOscTimeout 65pendingClipboardOscTimeout = 2 * DefaultEscTimeout 66t .Cleanup (func () {pendingClipboardOscTimeout = saved }) 67 68head := "\x1b]5522;type=read:status=DATA:id=x;QUJD" 69events := testReadInputs (t ,& stalledReader {chunks : []string {head ,"a" },pause :6 * DefaultEscTimeout }) 70want := []Event {UnknownEvent (head ),KeyPressEvent {Code :'a' ,Text :"a" }} 71if ! reflect .DeepEqual (events ,want ) { 72t .Fatalf ("events = %#v\nwant %#v" ,events ,want ) 73 } 74}