okami.mom/ultraviolet
git clone https://git.nkp.pet/okami.mom/ultraviolet
d4534d5
upstream
1package uv 2 3import ( 4"fmt" 5"testing" 6"time" 7) 8 9// TestInputLoopDoesNotReuseTheReadBuffer is the regression test for #176. the 10// input loop handed the event loop a slice of its own read buffer, and its 11// next read could overwrite those bytes before the event loop had copied them, 12// so one input sequence arrived as the bytes of the next. 13// 14// two different replies go in back to back, the way a terminal answers two 15// queries, and every round must produce them in order. 16func TestInputLoopDoesNotReuseTheReadBuffer (t * testing.T ) { 17const ( 18rounds = 2000 19decrpm = "\x1b[?1016;2$y" // a mode report, eleven bytes 20kitty = "\x1b_Gi=31;OK\x1b\\" // a kitty graphics reply; its first eleven bytes differ 21 ) 22 23con := newPipeConsole () 24tm := NewTerminal (con ,nil ) 25if err := tm .Start ();err != nil { 26t .Fatalf ("Start: %v" ,err ) 27 } 28defer stopAfterInputEnds (t ,tm ,con ) 29 30for i := range rounds { 31con .send (decrpm ) 32con .send (kitty ) 33got := nextReplies (tm ,2 ) 34if len (got )!= 2 || ! isModeReport (got [0 ])|| ! isKittyReply (got [1 ]) { 35t .Fatalf ("round %d: replies arrived as %s, want [uv.ModeReportEvent uv.KittyGraphicsEvent]" , 36i ,typesOf (got )) 37 } 38 } 39} 40 41// nextReplies collects up to n events other than the window size Start 42// reports on its own, and returns early with what it has if they stop 43// coming. a reply the corruption swallowed shows up as a short result, not a 44// hang. 45func nextReplies (tm * Terminal ,n int ) []Event { 46deadline := time .After (time .Second ) 47var got []Event 48for len (got )< n { 49select { 50case ev := <- tm .Events (): 51if _ ,ok := ev .(WindowSizeEvent );ok { 52continue 53 } 54got = append (got ,ev ) 55case <- deadline : 56return got 57 } 58 } 59return got 60} 61 62func isModeReport (ev Event )bool { 63_ ,ok := ev .(ModeReportEvent ) 64return ok 65} 66 67func isKittyReply (ev Event )bool { 68_ ,ok := ev .(KittyGraphicsEvent ) 69return ok 70} 71 72func typesOf (evs []Event )string { 73names := make ([]string ,len (evs )) 74for i ,ev := range evs { 75names [i ]= fmt .Sprintf ("%T" ,ev ) 76 } 77return fmt .Sprint (names ) 78}