ethr/ui.go
Pankaj Garg 46d0e6286c
Support for title in test results and improvement to handshake code. (#137)
* Take rate input as bits/s

* Update README.md

* Fix throttling to be as precise as possible.

* Minor doc fix.

* Update README.md

* Add support for title, improve handshake code.

* Update README.md
2020-12-02 02:08:55 -08:00

229 lines
5.1 KiB
Go

//-----------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license.
// See LICENSE.txt file in the project root for full license information.
//-----------------------------------------------------------------------------
package main
import (
"fmt"
"math"
"time"
"github.com/mattn/go-runewidth"
tm "github.com/nsf/termbox-go"
)
const (
lefttop = iota
horizontal
righttop
vertical
leftbottom
rightbottom
middlebottom
middletop
middleleft
middleright
middlemiddle
space
box1
box2
box3
box4
uparrow
dnarrow
)
var symbols = []rune{'┌', '─', '┐', '│', '└', '┘', '┴', '┬', '├', '┤', '┼', ' ', '░', '▒', '▓', '█', '↑', '↓'}
const (
justifyLeft = iota
justifyRight
justifyCenter
)
const (
border = iota
noBorder
)
type table struct {
ccount int
cwidth []int
x int
y int
cr int
justify int
border int
}
func init() {
if runewidth.IsEastAsian() {
symbols = []rune{'+', '-', '+', '|', '+', '+', '+', '+', '+', '+', '+', ' ', '░', '▒', '▓', '█', '^', 'v'}
}
}
func (t *table) drawTblRow(ledge, redge, middle, spr rune, fg, bg tm.Attribute) {
twidth := t.ccount + 1
for _, w := range t.cwidth {
twidth += w
}
for i := 0; i < twidth; i++ {
tm.SetCell(t.x+i, t.y+t.cr, middle, fg, bg)
}
if t.border == border {
tm.SetCell(t.x, t.y+t.cr, ledge, fg, bg)
tm.SetCell(t.x+twidth, t.y+t.cr, redge, fg, bg)
}
o := 0
for c, w := range t.cwidth {
o += w + 1
if c < t.ccount-1 {
tm.SetCell(t.x+o, t.y+t.cr, spr, fg, bg)
}
}
t.cr++
}
func (t *table) addTblRow(row []string) {
t.drawTblRow(symbols[vertical], symbols[vertical], symbols[space],
symbols[vertical], tm.ColorDefault, tm.ColorDefault)
t.cr--
o := 1
alignOffset := 0
for i := 0; i < t.ccount; i++ {
w := t.cwidth[i]
var s string
if t.justify == justifyLeft {
s = fmt.Sprintf("%-*s", w, row[i])
if i == 0 && t.border == noBorder {
alignOffset = -1
}
} else {
s = fmt.Sprintf("%*s", w, row[i])
}
printText(t.x+o+alignOffset, t.y+t.cr, w, s, tm.ColorDefault, tm.ColorDefault)
o += w + 1
alignOffset = 0
}
t.cr++
}
func (t *table) addTblSpr() {
t.drawTblRow(symbols[middleleft], symbols[middleright], symbols[horizontal],
symbols[middlemiddle], tm.ColorDefault, tm.ColorDefault)
}
func (t *table) addTblHdr() {
t.drawTblRow(symbols[lefttop], symbols[righttop], symbols[horizontal],
symbols[middletop], tm.ColorDefault, tm.ColorDefault)
}
func (t *table) addTblFtr() {
t.drawTblRow(symbols[leftbottom], symbols[rightbottom], symbols[horizontal],
symbols[middlebottom], tm.ColorDefault, tm.ColorDefault)
}
func printHLineText(x, y int, w int, text string) {
for i := 0; i < w; i++ {
tm.SetCell(x+i, y, symbols[horizontal], tm.ColorWhite, tm.ColorDefault)
}
offset := (w - runewidth.StringWidth(text)) / 2
textArr := []rune(text)
xoff := 0
for i := 0; i < len(text); i++ {
tm.SetCell(x+offset+i+xoff, y, textArr[i], tm.ColorWhite, tm.ColorDefault)
if runewidth.RuneWidth(textArr[i]) == 2 {
xoff++
}
}
}
func printVLine(x, y int, h int) {
tm.SetCell(x, y, symbols[middletop], tm.ColorWhite, tm.ColorDefault)
for i := 1; i < h; i++ {
tm.SetCell(x, y+i, symbols[vertical], tm.ColorWhite, tm.ColorDefault)
}
}
func printText(x, y, w int, text string, fg, bg tm.Attribute) {
textArr := []rune(text)
for i := 0; i < w; i++ {
tm.SetCell(x+i, y, ' ', fg, bg)
}
xoff := 0
for i := 0; i < len(textArr); i++ {
tm.SetCell(x+i+xoff, y, textArr[i], fg, bg)
if runewidth.RuneWidth(textArr[i]) == 2 {
xoff++
}
}
}
func printCenterText(x, y, w int, text string, fg, bg tm.Attribute) {
offset := (w - runewidth.StringWidth(text)) / 2
textArr := []rune(text)
for i := 0; i < w; i++ {
tm.SetCell(x+i, y, ' ', fg, bg)
}
xoff := 0
for i := 0; i < len(textArr); i++ {
tm.SetCell(x+offset+i+xoff, y, textArr[i], fg, bg)
if runewidth.RuneWidth(textArr[i]) == 2 {
xoff++
}
}
}
func printHLine(x, y int, w int) {
for i := 0; i < w; i++ {
tm.SetCell(x+i, y, symbols[horizontal], tm.ColorWhite, tm.ColorDefault)
}
}
func printUsageBar(x, y, w int, usage, scale uint64, clr tm.Attribute) {
barw := int(math.Log10(float64(uint64((usage + scale - 1) / (scale / 10)))))
if barw > w {
barw = w
} else if barw < 0 {
barw = 0
}
for j := 0; j < w; j++ {
tm.SetCell(x+j, y, symbols[box3], clr, tm.ColorDefault)
}
for j := 0; j < barw; j++ {
tm.SetCell(x+j, y, symbols[box3], clr|tm.AttrBold, clr)
}
}
func printDivider() {
ui.printMsg("-----------------------------------------------------------")
}
func printDivider2() {
ui.printMsg("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -")
}
type ethrUI interface {
fini()
getTitle() string
printMsg(format string, a ...interface{})
printErr(format string, a ...interface{})
printDbg(format string, a ...interface{})
paint(uint64)
emitTestHdr()
emitLatencyHdr()
emitLatencyResults(remote, proto string, avg, min, max, p50, p90, p95, p99, p999, p9999 time.Duration)
emitTestResultBegin()
emitTestResult(*ethrSession, EthrProtocol, uint64)
printTestResults([]string)
emitTestResultEnd()
emitStats(ethrNetStat)
}
var ui ethrUI