Codebase list golang-github-vbauerster-mpb / bad4074
Some decorators test Vladimir Bauer 8 years ago
5 changed file(s) with 185 addition(s) and 10 deletion(s). Raw diff Collapse all Expand all
313313 }
314314
315315 func draw(s *state, termWidth int, prependWs, appendWs *widthSync) []byte {
316 if len(s.prependFuncs) != len(prependWs.listen) || len(s.appendFuncs) != len(appendWs.listen) {
316 if len(s.prependFuncs) != len(prependWs.Listen) || len(s.appendFuncs) != len(appendWs.Listen) {
317317 return []byte{}
318318 }
319319 if termWidth <= 0 {
326326 var prependBlock []byte
327327 for i, f := range s.prependFuncs {
328328 prependBlock = append(prependBlock,
329 []byte(f(stat, prependWs.listen[i], prependWs.result[i]))...)
329 []byte(f(stat, prependWs.Listen[i], prependWs.Result[i]))...)
330330 }
331331
332332 // render append functions to the right of the bar
333333 var appendBlock []byte
334334 for i, f := range s.appendFuncs {
335335 appendBlock = append(appendBlock,
336 []byte(f(stat, appendWs.listen[i], appendWs.result[i]))...)
336 []byte(f(stat, appendWs.Listen[i], appendWs.Result[i]))...)
337337 }
338338
339339 prependCount := utf8.RuneCount(prependBlock)
4545 // DecoratorFunc is a function that can be prepended and appended to the progress bar
4646 type DecoratorFunc func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string
4747
48 // Name deprecated, use StaticName instead
4849 func Name(name string, minWidth int, conf byte) DecoratorFunc {
50 return StaticName(name, minWidth, conf)
51 }
52
53 // StaticName to be used, when there is no plan to change the name during whole
54 // life of a progress rendering process
55 func StaticName(name string, minWidth int, conf byte) DecoratorFunc {
56 nameFn := func(s *Statistics) string {
57 return name
58 }
59 return DynamicName(nameFn, minWidth, conf)
60 }
61
62 // DynamicName to be used, when there is a plan to chane the name once or
63 // several times during progress rendering process
64 func DynamicName(nameFn func(*Statistics) string, minWidth int, conf byte) DecoratorFunc {
4965 format := "%%"
5066 if (conf & DidentRight) != 0 {
5167 format += "-"
5268 }
5369 format += "%ds"
5470 return func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string {
71 name := nameFn(s)
5572 if (conf & DwidthSync) != 0 {
5673 myWidth <- utf8.RuneCountInString(name)
5774 max := <-maxWidth
0 package mpb_test
1
2 import (
3 "sync"
4 "testing"
5 "time"
6
7 . "github.com/vbauerster/mpb"
8 "github.com/vbauerster/mpb/decor"
9 )
10
11 func TestStaticName(t *testing.T) {
12 tests := []struct {
13 fn decor.DecoratorFunc
14 want string
15 }{
16 {
17 fn: decor.StaticName("Test", 0, 0),
18 want: "Test",
19 },
20 {
21 fn: decor.StaticName("Test", len("Test"), 0),
22 want: "Test",
23 },
24 {
25 fn: decor.StaticName("Test", 10, 0),
26 want: " Test",
27 },
28 {
29 fn: decor.StaticName("Test", 10, decor.DidentRight),
30 want: "Test ",
31 },
32 }
33
34 for _, test := range tests {
35 got := test.fn(nil, nil, nil)
36 if got != test.want {
37 t.Errorf("Want: %q, Got: %q\n", test.want, got)
38 }
39 }
40 }
41
42 type step struct {
43 stat *decor.Statistics
44 want string
45 }
46
47 func TestPercentageDwidthSync(t *testing.T) {
48
49 testCases := [][]step{
50 []step{
51 {&decor.Statistics{Total: 100, Current: 8}, "8 %"},
52 {&decor.Statistics{Total: 100, Current: 9}, "9 %"},
53 },
54 []step{
55 {&decor.Statistics{Total: 100, Current: 9}, " 9 %"},
56 {&decor.Statistics{Total: 100, Current: 10}, "10 %"},
57 },
58 []step{
59 {&decor.Statistics{Total: 100, Current: 9}, " 9 %"},
60 {&decor.Statistics{Total: 100, Current: 100}, "100 %"},
61 },
62 }
63
64 dfn := decor.Percentage(3, decor.DwidthSync)
65 testDecoratorConcurrently(t, dfn, testCases)
66 }
67
68 func TestPercentageDwidthSyncDidentRight(t *testing.T) {
69
70 testCases := [][]step{
71 []step{
72 {&decor.Statistics{Total: 100, Current: 8}, "8 %"},
73 {&decor.Statistics{Total: 100, Current: 9}, "9 %"},
74 },
75 []step{
76 {&decor.Statistics{Total: 100, Current: 9}, "9 % "},
77 {&decor.Statistics{Total: 100, Current: 10}, "10 %"},
78 },
79 []step{
80 {&decor.Statistics{Total: 100, Current: 9}, "9 % "},
81 {&decor.Statistics{Total: 100, Current: 100}, "100 %"},
82 },
83 }
84
85 dfn := decor.Percentage(3, decor.DwidthSync|decor.DidentRight)
86 testDecoratorConcurrently(t, dfn, testCases)
87 }
88
89 func TestPercentageDSyncSpace(t *testing.T) {
90
91 testCases := [][]step{
92 []step{
93 {&decor.Statistics{Total: 100, Current: 8}, " 8 %"},
94 {&decor.Statistics{Total: 100, Current: 9}, " 9 %"},
95 },
96 []step{
97 {&decor.Statistics{Total: 100, Current: 9}, " 9 %"},
98 {&decor.Statistics{Total: 100, Current: 10}, " 10 %"},
99 },
100 []step{
101 {&decor.Statistics{Total: 100, Current: 9}, " 9 %"},
102 {&decor.Statistics{Total: 100, Current: 100}, " 100 %"},
103 },
104 }
105
106 dfn := decor.Percentage(3, decor.DSyncSpace)
107 testDecoratorConcurrently(t, dfn, testCases)
108 }
109
110 func testDecoratorConcurrently(t *testing.T, dfn decor.DecoratorFunc, testCases [][]step) {
111 if len(testCases) == 0 {
112 t.Fail()
113 }
114
115 numBars := len(testCases[0])
116 var wg sync.WaitGroup
117 for _, columnCase := range testCases {
118 wg.Add(numBars)
119 timeout := make(chan struct{})
120 time.AfterFunc(100*time.Millisecond, func() {
121 close(timeout)
122 })
123 ws := NewWidthSync(timeout, numBars, 1)
124 res := make([]chan string, numBars)
125 for i := 0; i < numBars; i++ {
126 res[i] = make(chan string, 1)
127 go func(s step, ch chan string) {
128 defer wg.Done()
129 ch <- dfn(s.stat, ws.Listen[0], ws.Result[0])
130 }(columnCase[i], res[i])
131 }
132 wg.Wait()
133
134 var i int
135 for got := range fanIn(res...) {
136 want := columnCase[i].want
137 if got != want {
138 t.Errorf("Want: %q, Got: %q\n", want, got)
139 }
140 i++
141 }
142 }
143 }
144
145 func fanIn(in ...chan string) <-chan string {
146 ch := make(chan string)
147 go func() {
148 defer close(ch)
149 for _, ich := range in {
150 ch <- <-ich
151 }
152 }()
153 return ch
154 }
0 package mpb
1
2 var NewWidthSync = newWidthSync
1313 BeforeRender func([]*Bar)
1414
1515 widthSync struct {
16 listen []chan int
17 result []chan int
16 Listen []chan int
17 Result []chan int
1818 }
1919
2020 // progress config, fields are adjustable by user indirectly
236236
237237 func newWidthSync(timeout <-chan struct{}, numBars, numColumn int) *widthSync {
238238 ws := &widthSync{
239 listen: make([]chan int, numColumn),
240 result: make([]chan int, numColumn),
239 Listen: make([]chan int, numColumn),
240 Result: make([]chan int, numColumn),
241241 }
242242 for i := 0; i < numColumn; i++ {
243 ws.listen[i] = make(chan int, numBars)
244 ws.result[i] = make(chan int, numBars)
243 ws.Listen[i] = make(chan int, numBars)
244 ws.Result[i] = make(chan int, numBars)
245245 }
246246 for i := 0; i < numColumn; i++ {
247247 go func(listenCh <-chan int, resultCh chan<- int) {
266266 for i := 0; i < len(widths); i++ {
267267 resultCh <- result
268268 }
269 }(ws.listen[i], ws.result[i])
269 }(ws.Listen[i], ws.Result[i])
270270 }
271271 return ws
272272 }