// Copyright 2016 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package vmimpl

import (
	"bytes"
	"io"
	"testing"
	"time"

	"github.com/google/syzkaller/pkg/osutil"
)

func TestMerger(t *testing.T) {
	tee := new(bytes.Buffer)
	merger := NewOutputMerger(tee)

	rp1, wp1, err := osutil.LongPipe()
	if err != nil {
		t.Fatal(err)
	}
	defer wp1.Close()
	merger.Add("pipe1", rp1)

	rp2, wp2, err := osutil.LongPipe()
	if err != nil {
		t.Fatal(err)
	}
	defer wp2.Close()
	merger.Add("pipe2", rp2)

	wp1.Write([]byte("111"))
	select {
	case <-merger.Output:
		t.Fatalf("merger produced incomplete line")
	case <-time.After(10 * time.Millisecond):
	}

	wp2.Write([]byte("222"))
	select {
	case <-merger.Output:
		t.Fatalf("merger produced incomplete line")
	case <-time.After(10 * time.Millisecond):
	}

	wp1.Write([]byte("333\n444"))
	got := string(<-merger.Output)
	if want := "111333\n"; got != want {
		t.Fatalf("bad line: '%s', want '%s'", got, want)
	}

	wp2.Write([]byte("555\n666\n777"))
	got = string(<-merger.Output)
	if want := "222555\n666\n"; got != want {
		t.Fatalf("bad line: '%s', want '%s'", got, want)
	}

	wp1.Close()
	got = string(<-merger.Output)
	if want := "444\n"; got != want {
		t.Fatalf("bad line: '%s', want '%s'", got, want)
	}

	if err := <-merger.Err; err == nil {
		t.Fatalf("merger did not produce an error on pipe close")
	} else if merr := err.(MergerError); merr.Name != "pipe1" || merr.R != rp1 || merr.Err != io.EOF {
		t.Fatalf("merger produced wrong error: %v", err)
	}

	wp2.Close()
	got = string(<-merger.Output)
	if want := "777\n"; got != want {
		t.Fatalf("bad line: '%s', want '%s'", got, want)
	}

	merger.Wait()
	want := "111333\n222555\n666\n444\n777\n"
	if got := tee.String(); got != want {
		t.Fatalf("bad tee: '%s', want '%s'", got, want)
	}
}