github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/vm/vmimpl/merger_test.go (about)

     1  // Copyright 2016 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  package vmimpl
     5  
     6  import (
     7  	"bytes"
     8  	"errors"
     9  	"io"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/google/syzkaller/pkg/osutil"
    14  )
    15  
    16  func TestMerger(t *testing.T) {
    17  	tee := new(bytes.Buffer)
    18  	merger := NewOutputMerger(tee)
    19  
    20  	rp1, wp1, err := osutil.LongPipe()
    21  	if err != nil {
    22  		t.Fatal(err)
    23  	}
    24  	defer wp1.Close()
    25  	merger.Add("pipe1", rp1)
    26  
    27  	rp2, wp2, err := osutil.LongPipe()
    28  	if err != nil {
    29  		t.Fatal(err)
    30  	}
    31  	defer wp2.Close()
    32  	merger.Add("pipe2", rp2)
    33  
    34  	wp1.Write([]byte("111"))
    35  	select {
    36  	case <-merger.Output:
    37  		t.Fatalf("merger produced incomplete line")
    38  	case <-time.After(10 * time.Millisecond):
    39  	}
    40  
    41  	wp2.Write([]byte("222"))
    42  	select {
    43  	case <-merger.Output:
    44  		t.Fatalf("merger produced incomplete line")
    45  	case <-time.After(10 * time.Millisecond):
    46  	}
    47  
    48  	wp1.Write([]byte("333\n444\r"))
    49  	got := string(<-merger.Output)
    50  	if want := "111333\n"; got != want {
    51  		t.Fatalf("bad line: '%s', want '%s'", got, want)
    52  	}
    53  
    54  	wp2.Write([]byte("555\r\n666\n\r\r777"))
    55  	got = string(<-merger.Output)
    56  	if want := "222555\n666\n"; got != want {
    57  		t.Fatalf("bad line: '%s', want '%s'", got, want)
    58  	}
    59  
    60  	wp1.Close()
    61  	got = string(<-merger.Output)
    62  	if want := "444\n"; got != want {
    63  		t.Fatalf("bad line: '%s', want '%s'", got, want)
    64  	}
    65  
    66  	var merr MergerError
    67  	if err := <-merger.Err; err == nil {
    68  		t.Fatalf("merger did not produce an error on pipe close")
    69  	} else if !errors.As(err, &merr) || merr.Name != "pipe1" || merr.R != rp1 || merr.Err != io.EOF {
    70  		t.Fatalf("merger produced wrong error: %v", err)
    71  	}
    72  
    73  	wp2.Close()
    74  	got = string(<-merger.Output)
    75  	if want := "777\n"; got != want {
    76  		t.Fatalf("bad line: '%s', want '%s'", got, want)
    77  	}
    78  
    79  	merger.Wait()
    80  	want := "111333\n222555\n666\n444\n777\n"
    81  	if got := tee.String(); got != want {
    82  		t.Fatalf("bad tee: '%s', want '%s'", got, want)
    83  	}
    84  }