7c244da198
We use package 'tasklog' to print progress messages to the command line interface, as in the case of 'git-migrate-import(1)' or 'git-lfs-prune(1)'. This package aims to mimic the style of upstream Git's progress log lines, which are identical in every way, except for the trailing period at the end of 'done'. Git does print this period, but Git LFS does not. Let's make the two more similar by having LFS print this period, too.
210 lines
4.9 KiB
Go
210 lines
4.9 KiB
Go
package tasklog
|
|
|
|
import (
|
|
"bytes"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
type ChanTask chan *Update
|
|
|
|
func (e ChanTask) Updates() <-chan *Update { return e }
|
|
|
|
func (e ChanTask) Throttled() bool { return true }
|
|
|
|
type UnthrottledChanTask chan *Update
|
|
|
|
func (e UnthrottledChanTask) Updates() <-chan *Update { return e }
|
|
|
|
func (e UnthrottledChanTask) Throttled() bool { return false }
|
|
|
|
func TestLoggerLogsTasks(t *testing.T) {
|
|
var buf bytes.Buffer
|
|
|
|
task := make(chan *Update)
|
|
go func() {
|
|
task <- &Update{"first", time.Now(), false}
|
|
task <- &Update{"second", time.Now(), false}
|
|
close(task)
|
|
}()
|
|
|
|
l := NewLogger(&buf, ForceProgress(true))
|
|
l.throttle = 0
|
|
l.widthFn = func() int { return 0 }
|
|
l.Enqueue(ChanTask(task))
|
|
l.Close()
|
|
|
|
assert.Equal(t, "first\rsecond\rsecond, done.\n", buf.String())
|
|
}
|
|
|
|
func TestLoggerLogsSuppressesProgress(t *testing.T) {
|
|
var buf bytes.Buffer
|
|
|
|
task := make(chan *Update)
|
|
go func() {
|
|
task <- &Update{"first", time.Now(), false}
|
|
task <- &Update{"second", time.Now(), false}
|
|
close(task)
|
|
}()
|
|
|
|
l := NewLogger(&buf, ForceProgress(false))
|
|
l.throttle = 0
|
|
l.widthFn = func() int { return 0 }
|
|
l.Enqueue(ChanTask(task))
|
|
l.Close()
|
|
|
|
assert.Equal(t, "second, done.\n", buf.String())
|
|
}
|
|
|
|
func TestLoggerLogsMultipleTasksInOrder(t *testing.T) {
|
|
var buf bytes.Buffer
|
|
|
|
t1 := make(chan *Update)
|
|
go func() {
|
|
t1 <- &Update{"first", time.Now(), false}
|
|
t1 <- &Update{"second", time.Now(), false}
|
|
close(t1)
|
|
}()
|
|
t2 := make(chan *Update)
|
|
go func() {
|
|
t2 <- &Update{"third", time.Now(), false}
|
|
t2 <- &Update{"fourth", time.Now(), false}
|
|
close(t2)
|
|
}()
|
|
|
|
l := NewLogger(&buf, ForceProgress(true))
|
|
l.throttle = 0
|
|
l.widthFn = func() int { return 0 }
|
|
l.Enqueue(ChanTask(t1), ChanTask(t2))
|
|
l.Close()
|
|
|
|
assert.Equal(t, strings.Join([]string{
|
|
"first\r",
|
|
"second\r",
|
|
"second, done.\n",
|
|
"third\r",
|
|
"fourth\r",
|
|
"fourth, done.\n",
|
|
}, ""), buf.String())
|
|
}
|
|
|
|
func TestLoggerLogsMultipleTasksWithoutBlocking(t *testing.T) {
|
|
var buf bytes.Buffer
|
|
|
|
l := NewLogger(&buf, ForceProgress(true))
|
|
l.throttle = 0
|
|
t1, t2 := make(chan *Update), make(chan *Update)
|
|
|
|
l.widthFn = func() int { return 0 }
|
|
l.Enqueue(ChanTask(t1))
|
|
|
|
t1 <- &Update{"first", time.Now(), false}
|
|
l.Enqueue(ChanTask(t2))
|
|
close(t1)
|
|
t2 <- &Update{"second", time.Now(), false}
|
|
close(t2)
|
|
|
|
l.Close()
|
|
|
|
assert.Equal(t, strings.Join([]string{
|
|
"first\r",
|
|
"first, done.\n",
|
|
"second\r",
|
|
"second, done.\n",
|
|
}, ""), buf.String())
|
|
}
|
|
|
|
func TestLoggerThrottlesWrites(t *testing.T) {
|
|
var buf bytes.Buffer
|
|
|
|
t1 := make(chan *Update)
|
|
go func() {
|
|
start := time.Now()
|
|
|
|
t1 <- &Update{"first", start, false} // t = 0 ms, throttle was open
|
|
t1 <- &Update{"forced", start.Add(10 * time.Millisecond), true} // t = 10+ε ms, throttle is closed
|
|
t1 <- &Update{"second", start.Add(10 * time.Millisecond), false} // t = 10+ε ms, throttle is closed
|
|
t1 <- &Update{"third", start.Add(26 * time.Millisecond), false} // t = 20+ε ms, throttle was open
|
|
close(t1) // t = 20+2ε ms, throttle is closed
|
|
}()
|
|
|
|
l := NewLogger(&buf, ForceProgress(true))
|
|
l.widthFn = func() int { return 0 }
|
|
l.throttle = 15 * time.Millisecond
|
|
|
|
l.Enqueue(ChanTask(t1))
|
|
l.Close()
|
|
|
|
assert.Equal(t, strings.Join([]string{
|
|
"first\r",
|
|
"forced\r",
|
|
"third\r",
|
|
"third, done.\n",
|
|
}, ""), buf.String())
|
|
}
|
|
|
|
func TestLoggerThrottlesLastWrite(t *testing.T) {
|
|
var buf bytes.Buffer
|
|
|
|
t1 := make(chan *Update)
|
|
go func() {
|
|
start := time.Now()
|
|
|
|
t1 <- &Update{"first", start, false} // t = 0 ms, throttle was open
|
|
t1 <- &Update{"second", start.Add(10 * time.Millisecond), false} // t = 10+ε ms, throttle is closed
|
|
close(t1) // t = 10+2ε ms, throttle is closed
|
|
}()
|
|
|
|
l := NewLogger(&buf, ForceProgress(true))
|
|
l.widthFn = func() int { return 0 }
|
|
l.throttle = 15 * time.Millisecond
|
|
|
|
l.Enqueue(ChanTask(t1))
|
|
l.Close()
|
|
|
|
assert.Equal(t, strings.Join([]string{
|
|
"first\r",
|
|
"second, done.\n",
|
|
}, ""), buf.String())
|
|
}
|
|
|
|
func TestLoggerLogsAllDurableUpdates(t *testing.T) {
|
|
var buf bytes.Buffer
|
|
|
|
l := NewLogger(&buf, ForceProgress(true))
|
|
l.widthFn = func() int { return 0 }
|
|
l.throttle = 15 * time.Minute
|
|
|
|
t1 := make(chan *Update)
|
|
go func() {
|
|
t1 <- &Update{"first", time.Now(), false} // t = 0+ε ms, throttle is open
|
|
t1 <- &Update{"second", time.Now(), false} // t = 0+2ε ms, throttle is closed
|
|
close(t1) // t = 0+3ε ms, throttle is closed
|
|
}()
|
|
|
|
l.Enqueue(UnthrottledChanTask(t1))
|
|
l.Close()
|
|
|
|
assert.Equal(t, strings.Join([]string{
|
|
"first\r",
|
|
"second\r",
|
|
"second, done.\n",
|
|
}, ""), buf.String())
|
|
}
|
|
|
|
func TestLoggerHandlesSilentTasks(t *testing.T) {
|
|
var buf bytes.Buffer
|
|
|
|
task := make(chan *Update)
|
|
close(task)
|
|
|
|
l := NewLogger(&buf, ForceProgress(true))
|
|
l.Enqueue(ChanTask(task))
|
|
l.Close()
|
|
|
|
assert.Equal(t, "", buf.String())
|
|
}
|