//
//  tank, Import and Playlist Daemon for Aura project
//  Copyright (C) 2017-2020 Christian Pointner <equinox@helsinki.at>
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as
//  published by the Free Software Foundation, either version 3 of the
//  License, or (at your option) any later version.
//
//  This program 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 Affero General Public License for more details.
//
//  You should have received a copy of the GNU Affero General Public License
//  along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

package store

import (
	"io"
	"testing"
)

func TestLogEncodeDecode(t *testing.T) {
	var log1 Log
	log1.Append("stdout", "this is a test")
	log1.Append("stdout", "this is another test")
	log1.Append("stderr", "oh no something went wrong!")

	out, err := log1.encode()
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	var log2 Log
	if err = log2.decode(out); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	// reflect.DeepEqual does not use time.Equal... so we have to do this by hand...
	equal := false
	if len(log1.lines) == len(log2.lines) {
		for i := range log1.lines {
			if log1.lines[i].Stream != log2.lines[i].Stream {
				break
			}
			if log1.lines[i].Line != log2.lines[i].Line {
				break
			}
			if !log1.lines[i].Timestamp.Equal(log2.lines[i].Timestamp) {
				break
			}
		}
		equal = true
	}

	if !equal {
		t.Fatalf("logs are not equal: expected %+v, got %+v", log1.lines, log2.lines)
	}
}

func TestLogReader(t *testing.T) {
	var log Log
	var buf [1024]byte

	r := log.NewReader("")
	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 = log.NewReader("")
	for i, l := range log.lines {
		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 = log.NewReader("stderr")
	for i, l := range log.lines {
		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 = log.NewReader("stdout")
	for i, l := range log.lines {
		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)
	}
}