diff --git a/importer/fetch_converter_utils.go b/importer/fetch_converter_utils.go index b63fca012be7cc00194ab29d1231f0cc91c8ea84..642c339c21c314ece5370f8bbb453938b85cc884 100644 --- a/importer/fetch_converter_utils.go +++ b/importer/fetch_converter_utils.go @@ -81,3 +81,29 @@ func (l *convLogger) run() { func (l *convLogger) Wait() { <-l.done } + +// this is not a perfect io.Reader: +// - it will only return one line on each invocation even if len(p) would allow us to +// return more than one line +// - lines longer than len(p) will be truncated +type JobLogReader struct { + log JobLog + pos int + stream string +} + +func NewJobLogReader(log JobLog, stream string) *JobLogReader { + return &JobLogReader{log, -1, stream} +} + +func (r *JobLogReader) Read(p []byte) (n int, err error) { + for { + r.pos++ + if r.pos >= len(r.log) { + return 0, io.EOF + } + if r.stream == "" || r.log[r.pos].Stream == r.stream { + return copy(p, []byte(r.log[r.pos].Line)), nil + } + } +} diff --git a/importer/fetch_converter_utils_test.go b/importer/fetch_converter_utils_test.go new file mode 100644 index 0000000000000000000000000000000000000000..e38cc6ae2840eb55e04ac40adea45ec80542aa13 --- /dev/null +++ b/importer/fetch_converter_utils_test.go @@ -0,0 +1,102 @@ +// +// tank +// +// Import and Playlist Daemon for autoradio project +// +// +// Copyright (C) 2017-2018 Christian Pointner <equinox@helsinki.at> +// +// This file is part of tank. +// +// tank is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// tank is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with tank. If not, see <http://www.gnu.org/licenses/>. +// + +package importer + +import ( + "io" + "testing" +) + +func TestJobLogReader(t *testing.T) { + var log JobLog + var buf [1024]byte + + r := NewJobLogReader(log, "") + p := buf[:] + n, err := r.Read(p) + if n != 0 || err != io.EOF { + t.Fatalf("an empty log should yield %d, %v but got: %d, %v", 0, io.EOF, n, err) + } + + log.append("stdout", "this is a test") + log.append("stdout", "this is another test") + log.append("stderr", "oh no something went wrong!") + + r = NewJobLogReader(log, "") + for i, l := range log { + p = buf[:] + n, err = r.Read(p) + if n != len(l.Line) || err != nil { + t.Fatalf("reading line %d failed, expected return code %d, %v but got: %d, %v", i+1, len(l.Line), nil, n, err) + } + line := string(p[:n]) + if l.Line != line { + t.Fatalf("reading line %d failed, expected line %q but got: %q", i+1, l.Line, line) + } + } + if n, err = r.Read(p); n != 0 || err != io.EOF { + t.Fatalf("reading after the end of log should yield %d, %v but got: %d, %v", 0, io.EOF, n, err) + } + + r = NewJobLogReader(log, "stderr") + for i, l := range log { + if l.Stream != "stderr" { + continue + } + + p = buf[:] + n, err = r.Read(p) + if n != len(l.Line) || err != nil { + t.Fatalf("reading line %d failed, expected return code %d, %v but got: %d, %v", i+1, len(l.Line), nil, n, err) + } + line := string(p[:n]) + if l.Line != line { + t.Fatalf("reading line %d failed, expected line %q but got: %q", i+1, l.Line, line) + } + } + if n, err = r.Read(p); n != 0 || err != io.EOF { + t.Fatalf("reading after the end of log should yield %d, %v but got: %d, %v", 0, io.EOF, n, err) + } + + r = NewJobLogReader(log, "stdout") + for i, l := range log { + if l.Stream != "stdout" { + continue + } + + p = buf[:] + n, err = r.Read(p) + if n != len(l.Line) || err != nil { + t.Fatalf("reading line %d failed, expected return code %d, %v but got: %d, %v", i+1, len(l.Line), nil, n, err) + } + line := string(p[:n]) + if l.Line != line { + t.Fatalf("reading line %d failed, expected line %q but got: %q", i+1, l.Line, line) + } + } + if n, err = r.Read(p); n != 0 || err != io.EOF { + t.Fatalf("reading after the end of log should yield %d, %v but got: %d, %v", 0, io.EOF, n, err) + } +}