github.com/ericwq/aprilsh@v0.0.0-20240517091432-958bc568daa0/statesync/complete_test.go (about) 1 // Copyright 2022 wangqi. All rights reserved. 2 // Use of this source code is governed by a MIT-style 3 // license that can be found in the LICENSE file. 4 5 package statesync 6 7 import ( 8 "io" 9 "log/slog" 10 "math" 11 "reflect" 12 "strings" 13 "testing" 14 "time" 15 16 "github.com/ericwq/aprilsh/terminal" 17 "github.com/ericwq/aprilsh/util" 18 ) 19 20 func TestCompleteSubtract(t *testing.T) { 21 c, _ := NewComplete(8, 4, 4) 22 c.Subtract(c) // do nothing, just for coverage 23 c.GetEmulator() 24 } 25 26 func TestCompleteInitDiff(t *testing.T) { 27 c, _ := NewComplete(8, 4, 4) 28 got := c.InitDiff() 29 30 expect := "" 31 if expect != got { 32 t.Errorf("#test InitDiff() expect %q, got %q\n", expect, got) 33 } 34 } 35 36 func TestCompleteApplyString(t *testing.T) { 37 tc := []struct { 38 label string 39 seq string 40 width, height int 41 echoAck uint64 42 }{ 43 {"fill one row with string", "\x1B[4;4HErase to the end of line\x1B[0K.", 0, 0, 0}, 44 {"fill one row and resize", "\x1B[6;67HLAST", 70, 30, 0}, 45 {"fill one row and set ack", "\x1B[7;7H左边\x1B[7;77H中文", 0, 0, 3}, 46 } 47 48 util.Logger.CreateLogger(io.Discard, true, slog.LevelDebug) 49 // util.Logger.CreateLogger(os.Stdout, true, slog.LevelDebug) 50 51 for _, v := range tc { 52 c0, _ := NewComplete(80, 40, 40) 53 c1, _ := NewComplete(80, 40, 40) 54 55 // resize new state if necessary 56 if v.height != 0 && v.width != 0 { 57 r := terminal.Resize{Width: v.width, Height: v.height} 58 emu := c1.terminal 59 r.Handle(emu) 60 } 61 62 // print some data on screen 63 c1.terminal.HandleStream(v.seq) 64 65 // validate the equal is false 66 if c1.Equal(c0) { 67 t.Errorf("%q expect false equal(), got true", v.label) 68 } 69 70 // set echoAck for new state 71 if v.echoAck != 0 { 72 c1.echoAck = v.echoAck 73 } 74 75 // new state calculate difference with old state as parameter 76 diff := c1.DiffFrom(c0) 77 78 // apply to the old state 79 c0.ApplyString(diff) 80 81 // validate the result 82 if got := c0.DiffFrom(c1); got != "" { 83 // if !c0.Equal(c1) { 84 // got := c0.DiffFrom(c1) 85 t.Errorf("%q expect empty result after ApplyString(), got %q\n", v.label, got) 86 } 87 } 88 } 89 90 func TestApplyString_Fail(t *testing.T) { 91 diff := "mislead\n\x04:\x02@\x03\n2\x120\"." 92 93 c, _ := NewComplete(80, 40, 40) 94 if err := c.ApplyString(diff); err == nil { 95 t.Error("#test feed ApplyString with wrong parameter, expect error.") 96 } 97 } 98 99 func TestCompleteSetEchoAck(t *testing.T) { 100 tc := []struct { 101 label string 102 data []pair 103 expect bool 104 }{ 105 {"find two states", []pair{{1, 49}, {2, 43}, {3, 52}}, true}, 106 {"too quick to find the latest state", []pair{{1, 9}, {2, 13}, {3, 12}}, false}, 107 } 108 109 c, _ := NewComplete(8, 4, 4) 110 now := time.Now().UnixMilli() 111 112 for _, v := range tc { 113 // reset history 114 c.inputHistory = make([]pair, 0) 115 c.echoAck = 0 116 117 // register the frame number and time 118 var ts int64 = 0 119 for _, p := range v.data { 120 121 ts += p.timestamp 122 // note: the timestamp is delta value in ms. 123 c.RegisterInputFrame(p.frameNum, now+ts) 124 // fmt.Printf("#test setEchoAck timestamp=%d, ts=%d\n", p.timestamp, ts) 125 } 126 127 // fmt.Printf("#test setEchoAck inputHistory = %v\n", c.inputHistory) 128 129 got := c.SetEchoAck(now + ts) 130 // fmt.Printf("#test setEchoAck inputHistory = %v\n", c.inputHistory) 131 if v.expect != got { 132 t.Errorf("%q expect %t, got %t\n", v.label, v.expect, got) 133 } 134 } 135 } 136 137 func TestCompleteWaitTime(t *testing.T) { 138 tc := []struct { 139 label string 140 data []pair 141 time int64 142 expect int 143 }{ 144 {"history size <2", []pair{{1, 49}}, 0, math.MaxInt}, 145 {"now < last +50 ", []pair{{1, 49}, {2, 43}}, 9, 50 - 9}, 146 {"last +50 <= now", []pair{{1, 49}, {2, 43}}, 50, 0}, 147 } 148 149 c, _ := NewComplete(8, 4, 4) 150 now := time.Now().UnixMilli() 151 152 for _, v := range tc { 153 // reset history 154 c.inputHistory = make([]pair, 0) 155 c.echoAck = 0 156 157 // register the frame number and time 158 var ts int64 = 0 159 for _, p := range v.data { 160 161 ts += p.timestamp 162 // note: the timestamp is delta value in ms. 163 c.RegisterInputFrame(p.frameNum, now+ts) 164 // fmt.Printf("#test setEchoAck timestamp=%d, ts=%d\n", p.timestamp, ts) 165 } 166 167 got := c.WaitTime(now + ts + v.time) 168 if v.expect != got { 169 t.Errorf("%q expect %d, got %d\n", v.label, v.expect, got) 170 } 171 } 172 } 173 174 func TestCompleteResetInput(t *testing.T) { 175 c, _ := NewComplete(8, 4, 4) 176 177 c.ResetInput() 178 if c.terminal.GetCursorCol() != 0 || c.terminal.GetCursorRow() != 0 { 179 t.Errorf("#test after resetInput() the cursor should be in (0,0), got (%d,%d)\n", 180 c.terminal.GetCursorRow(), c.terminal.GetCursorCol()) 181 } 182 } 183 184 func TestCompleteClone(t *testing.T) { 185 c, _ := NewComplete(8, 4, 4) 186 clone := c.Clone() 187 188 if !c.Equal(clone) { 189 t.Errorf("#test clone expect %v, got %v\n", c, clone) 190 } 191 } 192 193 func TestDiffFrom(t *testing.T) { 194 tc := []struct { 195 label string 196 nCols, nRows int // screen size 197 seq1 []string // sequence before action 198 seq2 []string // sequence after action 199 resp string 200 }{ 201 {"simple case", 80, 40, []string{}, 202 []string{ 203 "nvide:0.8.9\r\n", 204 "\r\nLua, C/C++ and Golang Integrated Development Environment.\r\nPowered by neovim, luals, gopls and clangd.\r\n", "\x1b]0;aprilsh\a", 205 "ide@openrc-nvide:~/develop $ \x1b[6n"}, "\x1b[5;30R"}, 206 {"vi and quit", 80, 40, 207 []string{ 208 "\x1b]0;aprilsh\a", // set title to avoid title stack warning 209 /*vi start*/ "\x1b[?1049h\x1b[22;0;0t\x1b[?1h\x1b=\x1b[H\x1b[2J\x1b]11;?\a\x1b[?2004h\x1b[?u\x1b[c\x1b[?25h", 210 // "\x1b]11;rgb:0000/0000/0000\x1b\\\x1b[?64;1;9;15;21;22c" 211 /*clear screen*/ "\x1b[?25l\x1b(B\x1b[m\x1b[H\x1b[2J\x1b[>4;2m\x1b]112\a\x1b[2 q\x1b[?1002h\x1b[?1006h\x1b[38;2;233;233;244m\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[J\x1b[H", 212 /*vi file*/ "\x1b(B\x1b[m\x1b[38;2;98;100;131m \x1b(B\x1b[m\x1b[38;2;248;248;242m1 \x1b(B\x1b[m\x1b[38;2;233;233;244m\x1b[48;2;45;48;62mgo 1.19 \r\n\x1b(B\x1b[m\x1b[38;2;98;100;131m \x1b(B\x1b[m\x1b[38;2;94;95;105m2 \x1b(B\x1b[m\x1b[38;2;233;233;244m\x1b[K\r\n\x1b(B\x1b[m\x1b[38;2;98;100;131m \x1b(B\x1b[m\x1b[38;2;94;95;105m3 \x1b(B\x1b[m\x1b[38;2;233;233;244muse (\x1b[K\r\n\x1b(B\x1b[m\x1b[38;2;98;100;131m \x1b(B\x1b[m\x1b[38;2;94;95;105m4 \x1b(B\x1b[m\x1b[38;2;233;233;244m ./aprilsh\x1b[K\r\n\x1b(B\x1b[m\x1b[38;2;98;100;131m \x1b(B\x1b[m\x1b[38;2;94;95;105m5 \x1b(B\x1b[m\x1b[38;2;233;233;244m ./terminfo\x1b[K\r\n\x1b(B\x1b[m\x1b[38;2;98;100;131m \x1b(B\x1b[m\x1b[38;2;94;95;105m6 \x1b(B\x1b[m\x1b[38;2;233;233;244m)\x1b[K\x1b(B\x1b[m\x1b[38;2;98;100;131m\r\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b[K\n\x1b(B\x1b[0;1m\x1b[38;2;40;42;54m\x1b[48;2;139;155;205m \ue7c5\x1b[39;3H NORMAL\x1b(B\x1b[m\x1b[38;2;139;155;205m\x1b[48;2;94;95;105m\ue0bc\x1b[39;11H \x1b(B\x1b[m\x1b[38;2;94;95;105m\x1b[48;2;65;67;79m\ue0bc\x1b[39;13H \x1b(B\x1b[m\x1b[38;2;248;248;242m\x1b[48;2;65;67;79m go.work \x1b(B\x1b[m\x1b[38;2;65;67;79m\ue0bc\x1b[39;24H \x1b(B\x1b[m\x1b[38;2;255;112;112m\ue0b6\x1b[39;146H\x1b(B\x1b[m\x1b[38;2;55;56;68m\x1b[48;2;255;112;112m\U000f024b\x1b[39;147H \x1b(B\x1b[m\x1b[38;2;248;248;242m\x1b[48;2;65;67;79m develop \x1b(B\x1b[m\x1b[38;2;80;250;123m\x1b[48;2;65;67;79m\ue0b6\x1b[39;158H\x1b(B\x1b[m\x1b[38;2;40;42;54m\x1b[48;2;80;250;123m\ue612\x1b[39;159H \x1b(B\x1b[m\x1b[38;2;80;250;123m\x1b[48;2;65;67;79m Top \x1b(B\x1b[m\x1b[38;2;233;233;244m\r\n\x1b[J\x1b]112\a\x1b[2 q\x1b[1;5H\x1b[?25h", 213 /*screen border*/ "\x1b[?25l\n\n\n\x1b(B\x1b[m\x1b[38;2;60;61;73m│\x1b[4;6H \x1b[5;5H│\x1b[5;6H \x1b[1;5H\x1b[?25h", 214 /*loading*/ "\x1b[?25l\x1b[39;52H\x1b(B\x1b[m\x1b[38;2;80;250;123m \U000f0aa2\x1b[39;54H Setting up workspace Loading packages... (0%) \x1b(B\x1b[m\x1b[38;2;139;155;205m \uf085\x1b[39;131H LSP ~ gopls \x1b[1;5H\x1b[?25h", 215 /*loading*/ "\x1b[?25l\x1b[39;49H\x1b(B\x1b[m\x1b[38;2;80;250;123m \U000f0aa2\x1b[39;51H Setting up workspace Finished loading packages. (0%)\x1b[1;5H\x1b[?25h", 216 /*loading*/ "\x1b[?25l\x1b[39;49H\x1b(B\x1b[m\x1b[38;2;65;67;79m \x1b[1;5H\x1b[?25h", 217 }, 218 []string{ 219 /*1st sequence after :q*/ "\x1b[?25l\r\x1b[40;1H\x1b[?25h", 220 /*2nd sequence after :q*/ "\x1b[?25l\x1b]112\a\x1b[2 q\x1b[?25h", 221 /*3rd sequence after :q*/ "\x1b[?25l\x1b]112\a\x1b[2 q\x1b[?1002l\x1b[?1006l\x1b(B\x1b[m\x1b[?25h\x1b[?1l\x1b>\x1b[>4;0m\x1b[?1049l\x1b[23;0;0t\x1b[?2004l\x1b[?1004l\x1b[?25h", 222 /*4th sequence after :q*/ "ide@openrc-nvide:~/develop $ \x1b[6n", 223 }, "\x1b[1;30R"}, 224 {"screen with content then vi utf-8 file", 80, 40, 225 []string{ 226 "\x1b]0;aprilsh\a", // set title to avoid title stack warning 227 "ide@openrc-nvide:~/develop $ \x1b[6n"}, 228 []string{ 229 "\x1b[?1049h\x1b[22;0;0t\x1b[?1h\x1b=\x1b[H\x1b[2J\x1b]11;?\a\x1b[?2004h\x1b[?u\x1b[c\x1b[?25h", 230 }, "\x1b]11;rgb:0000/0000/0000\x1b\\\x1b[?64;1;9;15;21;22c"}, 231 {"cat file larger than screen rows", 80, 40, 232 []string{ 233 "nvide:0.8.9\r\n\r\nLua, C/C++ and Golang Integrated Development Environment.\r\nPowered by neovim, luals, gopls and clangd.\r\n", 234 "\x1b]0;aprilsh\a", 235 "ide@openrc-nvide:~ $ cd develop\r\n", 236 "ide@openrc-nvide:~/develop $ ls\r\n", 237 "\x1b[1;34mNvChad\x1b[m \x1b[0;0mgit.md\x1b[m \x1b[1;34mgolangIDE\x1b[m \x1b[1;34mneovim-lua\x1b[m \x1b[1;34ms6\x1b[m\r\n\x1b[1;34maprilsh\x1b[m \x1b[0;0mgo.work\x1b[m \x1b[1;34mmosh\x1b[m \x1b[1;34mnvide\x1b[m \x1b[1;34mtelescope.nvim\x1b[m\r\n\x1b[1;34mdotfiles\x1b[m \x1b[0;0mgo.work.sum\x1b[m \x1b[0;0mmosh-1.3.2.tar.gz\x1b[m \x1b[0;0mpersonal-access-token.txt\x1b[m \x1b[1;34mterminfo\x1b[m\r\n", 238 "ide@openrc-nvide:~/develop $ cat tokens.txt\r\n", 239 }, 240 []string{"111\r\naaa\r\nbbb\r\n\r\nccc\r\nddd\r\n\r\neeee\r\nffff\r\n\r\nggg\r\nhhh#\r\n\r\napp\r\niii\r\n\r\njjj\r\nkkk#\r\n\r\nlll\r\nmmm\r\n\r\n#nnn \r\n\r\nooo.\r\nppp\r\n\r\nqqq\r\nrrr\r\nsss\r\nttt\r\n\r\n隐uuu\r\n方式vvv\r\niwww\r\nxxx\r\n\r\nyyy\r\nzzz\r\n\r\n专用aaa\r\nbbb\r\nccc\r\nddd\r\n\r\neee\r\nfff\r\nggg\r\n"}, // total 48 \n 241 ""}, 242 {"return on last row", 101, 24, 243 []string{"nvide:0.8.9\r\n", 244 "\r\nLua, C/C++ and Golang Integrated Development Environment.\r\nPowered by neovim, luals, gopls and clangd.\r\n", 245 "\x1b]0;aprilsh\a", 246 "ide@openrc-nvide:~ $ ls\r\n", 247 "\x1b[1;34mdevelop\x1b[m \x1b[1;34mproj\x1b[m\r\n", 248 "ide@openrc-nvide:~ $ cd develop\r\n", 249 "ide@openrc-nvide:~/develop $ ls -al\r\n", 250 "total 1696\r\ndrwxr-xr-x 22 ide develop 704 Oct 26 20:28 \x1b[1;34m.\x1b[m\r\ndrwxr-sr-x 1 ide develop 4096 Oct 26 21:08 \x1b[1;34m..\x1b[m\r\n-rw-r--r-- 1 ide develop 8196 Sep 15 22:10 \x1b[0;0m.DS_Store\x1b[m\r\ndrwxr-xr-x 19 ide develop 608 Oct 27 19:13 \x1b[1;34maprilsh\x1b[m\r\ndrwxr-xr-x 14 ide develop 448 May 26 2022 \x1b[1;34mdocTerminal\x1b[m\r\ndrwxr-xr-x 29 ide develop 928 Aug 7 22:02 \x1b[1;34mexamples\x1b[m\r\n-rw-r--r-- 1 ide develop 50 May 21 14:35 \x1b[0;0mgo.work\x1b[m\r\n-rw-r--r-- 1 ide develop 694 Aug 5 22:36 \x1b[0;0mgo.work.sum\x1b[m\r\ndrwxr-xr-x 18 ide develop 576 Jun 24 22:36 \x1b[1;34mgoutmp\x1b[m\r\ndrwxr-xr-x 9 ide develop 288 Dec 17 2020 \x1b[1;34mgskills\x1b[m\r\n-rwxr-xr-x 1 ide develop 1484717 Nov 15 2021 \x1b[1;32mgskills.key\x1b[m\r\ndrwxr-xr-x 6 ide develop 192 Nov 15 2021 \x1b[1;34mimages\x1b[m\r\ndrwxr-sr-x 32 ide develop 1024 May 9 2021 \x1b[1;34mldd3\x1b[m\r\ndrwxr-xr-x 16 ide develop 512 Jun 15 21:48 \x1b[1;34mlibutempter\x1b[m\r\ndrwxr-xr-x 51 ide develop 1632 Apr 30 2022 \x1b[1;34mncurses-6.3\x1b[m\r\ndrwxr-xr-x 14 ide develop 448 Sep 27 22:01 \x1b[1;34mnvide\x1b[m\r\n-rw-rw-rw- 1 ide develop 782 Oct 26 20:27 \x1b[0;0mpersonal-access-token.txt\x1b[m\r\ndrwxr-xr-x 10 ide develop 320 May 30 18:59 \x1b[1;34ms6\x1b[m\r\ndrwxr-xr-x 33 ide develop 1056 Jun 28 06:17 \x1b[1;34mterminfo\x1b[m\r\ndrwxr-xr-x 82 ide develop 2624 May 11 2022 \x1b[1;34mvttest-20220215\x1b[m\r\n-rw-r--r-- 1 ide develop 216949 May 11 2022 \x1b[0;0mvttest.tar.gz\x1b[m\r\ndrwxr-xr-x 5 ide develop 160 May 2 2022 \x1b[1;34mworkspace\x1b[m\r\nide@openrc-nvide:~/develop $ ", 251 }, 252 []string{"\r\n"}, 253 ""}, 254 {"write on ring buffer", 8, 4, 255 []string{"8888888\r\na\r\nb\r\nc\r\n", 256 "a1\r\na2\r\na3\r\na4\r\n", 257 "b2\r\nb2\r\nb3\r\nb4\r\n", 258 "c2\r\nc2\r\nc3\r\nc4\r\n", 259 }, 260 []string{"x1\r\nx2\r\nx3\r\nx4\r\n"}, ""}, 261 } 262 263 util.Logger.CreateLogger(io.Discard, true, slog.LevelDebug) 264 // util.Logger.CreateLogger(os.Stderr, true, slog.LevelDebug) 265 266 for _, v := range tc { 267 t.Run(v.label, func(t *testing.T) { 268 savedLines := v.nRows * 3 269 270 a, _ := NewComplete(v.nCols, v.nRows, savedLines) 271 c, _ := NewComplete(v.nCols, v.nRows, savedLines) 272 273 // fmt.Printf("#TestDiffFrom point=%d\n", 333) 274 // assumed state prepare 275 var t2 strings.Builder 276 var ss strings.Builder 277 for i := range v.seq1 { 278 ss.WriteString(v.seq1[i]) 279 } 280 t2.WriteString(a.Act(ss.String())) 281 // fmt.Printf("#TestDiffFrom point=%d\n", 444) 282 c.Act(ss.String()) 283 284 if !c.EqualTrace(a) { 285 t.Errorf("%s: prepare stage error\n", v.label) 286 } 287 c.Reset() 288 a.Reset() 289 290 // current state changed after :q command 291 t2.Reset() 292 ss.Reset() 293 for i := range v.seq2 { 294 ss.WriteString(v.seq2[i]) 295 } 296 297 t2.WriteString(c.Act(ss.String())) 298 if v.resp != t2.String() { 299 t.Errorf("%s: terminal response expect %q, got %q\n", v.label, v.resp, t2.String()) 300 } 301 302 // util.Log.Debug("TestDiffFrom","point", 601) 303 diff := c.DiffFrom(a) 304 // util.Log.Debug("TestDiffFrom","point", 602) 305 306 n := a.Clone() 307 n.ApplyString(diff) 308 if !c.EqualTrace(n) { 309 t.Errorf("%s: round-trip Instruction verification failed!", v.label) 310 t.Logf("%s: diff=%q", v.label, diff) 311 } 312 313 // util.Log.Debug("TestDiffFrom","point", 603) 314 cd := c.InitDiff() 315 // util.Log.Debug("TestDiffFrom","point", 604) 316 nd := n.InitDiff() 317 // util.Log.Debug("TestDiffFrom","point", 605) 318 if cd != nd { 319 t.Errorf("%s: target state Instruction verification failed!", v.label) 320 // t.Logf("current state diff=%q", cd) 321 // t.Logf("new state diff=%q", nd) 322 } 323 }) 324 } 325 } 326 327 func TestEqual(t *testing.T) { 328 tc := []struct { 329 label string 330 seq0 string 331 seq1 string 332 }{ 333 {"custom equal", "\x1B[6;67HLAST\x1B[1;7H", "\x1B[6;67HLAST\x1B[1;7H"}, 334 // {"fill one row and set ack", "\x1B[7;7H左边\x1B[7;77H中文", 0, 0, 3}, 335 } 336 v := tc[0] 337 c0, _ := NewComplete(80, 40, 40) 338 c1, _ := NewComplete(80, 40, 40) 339 340 c0.terminal.HandleStream(v.seq0) 341 c1.terminal.HandleStream(v.seq1) 342 343 if !c0.Equal(c1) { 344 t.Errorf("%q expect not equal object\n", v.label) 345 } 346 } 347 348 func (c *Complete) equalDiffFrom(x *Complete) bool { 349 // use DiffFrom to compare the state 350 if diff := c.DiffFrom(x); diff != "" { 351 return false 352 } 353 return true 354 // return reflect.DeepEqual(c.terminal, x.terminal) && c.echoAck == x.echoAck 355 } 356 357 func (c *Complete) deepEqual(x *Complete) bool { 358 return reflect.DeepEqual(c.terminal, x.terminal) && c.echoAck == x.echoAck 359 } 360 361 // check Equal mthod 362 // func (c *Complete) customEqual(x *Complete) bool { 363 // if c.echoAck != x.echoAck { 364 // return false 365 // } 366 // 367 // return c.terminal.Equal(x.terminal) 368 // } 369 370 // https://blog.logrocket.com/benchmarking-golang-improve-function-performance/ 371 // https://coder.today/tech/2018-11-10_profiling-your-golang-app-in-3-steps/ 372 // https://www.speedscope.app/ 373 func BenchmarkDiffFromEqual(b *testing.B) { 374 tc := []struct { 375 label string 376 seq0 string 377 seq1 string 378 }{ 379 {"fill one row with string", "\x1B[6;67HLAST", "\x1B[6;67HLAST"}, 380 // {"fill one row and set ack", "\x1B[7;7H左边\x1B[7;77H中文", 0, 0, 3}, 381 } 382 v := tc[0] 383 c0, _ := NewComplete(80, 40, 40) 384 c1, _ := NewComplete(80, 40, 40) 385 386 c0.terminal.HandleStream(v.seq0) 387 c1.terminal.HandleStream(v.seq1) 388 389 for i := 0; i < b.N; i++ { 390 c0.equalDiffFrom(c1) 391 } 392 } 393 394 func BenchmarkDeepEqual(b *testing.B) { 395 tc := []struct { 396 label string 397 seq0 string 398 seq1 string 399 }{ 400 {"fill one row with string", "\x1B[6;67HLAST", "\x1B[6;67HLAST"}, 401 // {"fill one row and set ack", "\x1B[7;7H左边\x1B[7;77H中文", 0, 0, 3}, 402 } 403 v := tc[0] 404 c0, _ := NewComplete(80, 40, 40) 405 c1, _ := NewComplete(80, 40, 40) 406 407 c0.terminal.HandleStream(v.seq0) 408 c1.terminal.HandleStream(v.seq1) 409 410 for i := 0; i < b.N; i++ { 411 c0.deepEqual(c1) 412 } 413 } 414 415 func BenchmarkEqual(b *testing.B) { 416 tc := []struct { 417 label string 418 seq0 string 419 seq1 string 420 }{ 421 {"fill one row with string", "\x1B[6;67HLAST", "\x1B[6;67HLAST"}, 422 // {"fill one row and set ack", "\x1B[7;7H左边\x1B[7;77H中文", 0, 0, 3}, 423 } 424 v := tc[0] 425 c0, _ := NewComplete(80, 40, 40) 426 c1, _ := NewComplete(80, 40, 40) 427 428 c0.terminal.HandleStream(v.seq0) 429 c1.terminal.HandleStream(v.seq1) 430 431 for i := 0; i < b.N; i++ { 432 c0.Equal(c1) 433 } 434 } 435 436 func BenchmarkDiffFrom(b *testing.B) { 437 tc := []struct { 438 label string 439 seq0 string 440 seq1 string 441 }{ 442 {"fill one row with string", "\x1B[4;4HErase to the end of line\x1B[0K.", "\x1B[6;67HLAST"}, 443 // {"fill one row and set ack", "\x1B[7;7H左边\x1B[7;77H中文", 0, 0, 3}, 444 } 445 v := tc[0] 446 c0, _ := NewComplete(80, 40, 40) 447 c1, _ := NewComplete(80, 40, 40) 448 449 c0.terminal.HandleStream(v.seq0) 450 c1.terminal.HandleStream(v.seq1) 451 452 for i := 0; i < b.N; i++ { 453 c0.DiffFrom(c1) 454 } 455 } 456 457 func BenchmarkFramebuffer_Equal(b *testing.B) { 458 tc := []struct { 459 label string 460 seq0 string 461 seq1 string 462 }{ 463 {"fill one row with string", "\x1B[4;4HErase to the end of line\x1B[0K.", "\x1B[6;67HLAST"}, 464 // {"fill one row and set ack", "\x1B[7;7H左边\x1B[7;77H中文", 0, 0, 3}, 465 } 466 v := tc[0] 467 c0, _ := NewComplete(80, 40, 40) 468 c1, _ := NewComplete(80, 40, 40) 469 470 c0.terminal.HandleStream(v.seq0) 471 c1.terminal.HandleStream(v.seq1) 472 473 for i := 0; i < b.N; i++ { 474 c0.getFramebuffer().Equal(c1.getFramebuffer()) 475 } 476 } 477 478 func BenchmarkNewFrame(b *testing.B) { 479 tc := []struct { 480 label string 481 seq0 string 482 seq1 string 483 }{ 484 {"fill one row with string", "\x1B[4;4HErase to the end of line\x1B[0K.", "\x1B[6;67HLAST"}, 485 // {"fill one row and set ack", "\x1B[7;7H左边\x1B[7;77H中文", 0, 0, 3}, 486 } 487 v := tc[0] 488 c0, _ := NewComplete(80, 40, 40) 489 c1, _ := NewComplete(80, 40, 40) 490 491 c0.terminal.HandleStream(v.seq0) 492 c1.terminal.HandleStream(v.seq1) 493 494 for i := 0; i < b.N; i++ { 495 c0.display.NewFrame(true, c0.terminal, c1.terminal) 496 } 497 }