Merge pull request #50 from featalion/newline-fix
PR #40 with test case closes #35 and closes #40
This commit is contained in:
commit
f9f753ab01
29
tail.go
29
tail.go
|
@ -211,10 +211,17 @@ func (tail *Tail) tailFileSync() {
|
|||
|
||||
// Read line by line.
|
||||
for {
|
||||
// grab the position in case we need to back up in the event of a half-line
|
||||
offset, err := tail.Tell()
|
||||
if err != nil {
|
||||
tail.Kill(err)
|
||||
return
|
||||
}
|
||||
|
||||
line, err := tail.readLine()
|
||||
|
||||
// Process `line` even if err is EOF.
|
||||
if err == nil || (err == io.EOF && line != "") {
|
||||
if err == nil {
|
||||
cooloff := !tail.sendLine(line)
|
||||
if cooloff {
|
||||
// Wait a second before seeking till the end of
|
||||
|
@ -236,8 +243,22 @@ func (tail *Tail) tailFileSync() {
|
|||
}
|
||||
} else if err == io.EOF {
|
||||
if !tail.Follow {
|
||||
if line != "" {
|
||||
tail.sendLine(line)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if tail.Follow && line != "" {
|
||||
// this has the potential to never return the last line if
|
||||
// it's not followed by a newline; seems a fair trade here
|
||||
err := tail.seekTo(SeekInfo{Offset: offset, Whence: 0})
|
||||
if err != nil {
|
||||
tail.Kill(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// When EOF is reached, wait for more data to become
|
||||
// available. Wait strategy is based on the `tail.watcher`
|
||||
// implementation (inotify or polling).
|
||||
|
@ -317,7 +338,11 @@ func (tail *Tail) openReader() {
|
|||
}
|
||||
|
||||
func (tail *Tail) seekEnd() error {
|
||||
_, err := tail.file.Seek(0, 2)
|
||||
return tail.seekTo(SeekInfo{Offset: 0, Whence: 2})
|
||||
}
|
||||
|
||||
func (tail *Tail) seekTo(pos SeekInfo) error {
|
||||
_, err := tail.file.Seek(pos.Offset, pos.Whence)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Seek error on %s: %s", tail.Filename, err)
|
||||
}
|
||||
|
|
17
tail_test.go
17
tail_test.go
|
@ -54,11 +54,11 @@ func TestStop(t *testing.T) {
|
|||
Cleanup()
|
||||
}
|
||||
|
||||
func TestMaxLineSize(_t *testing.T) {
|
||||
func MaxLineSizeT(_t *testing.T, follow bool, fileContent string, expected []string) {
|
||||
t := NewTailTest("maxlinesize", _t)
|
||||
t.CreateFile("test.txt", "hello\nworld\nfin\nhe")
|
||||
tail := t.StartTail("test.txt", Config{Follow: true, Location: nil, MaxLineSize: 3})
|
||||
go t.VerifyTailOutput(tail, []string{"hel", "lo", "wor", "ld", "fin", "he"})
|
||||
t.CreateFile("test.txt", fileContent)
|
||||
tail := t.StartTail("test.txt", Config{Follow: follow, Location: nil, MaxLineSize: 3})
|
||||
go t.VerifyTailOutput(tail, expected)
|
||||
|
||||
// Delete after a reasonable delay, to give tail sufficient time
|
||||
// to read all lines.
|
||||
|
@ -68,6 +68,15 @@ func TestMaxLineSize(_t *testing.T) {
|
|||
Cleanup()
|
||||
}
|
||||
|
||||
func TestMaxLineSizeFollow(_t *testing.T) {
|
||||
// As last file line does not end with newline, it will not be present in tail's output
|
||||
MaxLineSizeT(_t, true, "hello\nworld\nfin\nhe", []string{"hel", "lo", "wor", "ld", "fin"})
|
||||
}
|
||||
|
||||
func TestMaxLineSizeNoFollow(_t *testing.T) {
|
||||
MaxLineSizeT(_t, false, "hello\nworld\nfin\nhe", []string{"hel", "lo", "wor", "ld", "fin", "he"})
|
||||
}
|
||||
|
||||
func TestOver4096ByteLine(_t *testing.T) {
|
||||
t := NewTailTest("Over4096ByteLine", _t)
|
||||
testString := strings.Repeat("a", 4097)
|
||||
|
|
Loading…
Reference in New Issue