syzkaller/vm/vmimpl/merger_test.go
Dmitry Vyukov af643baa32 vm: overhaul
VM infrastructure currently has several problems:
 - Config struct is complete mess with a superset of params for all VM types
 - verification of Config is mess spread across several places
 - there is no place where VM code could do global initialization
   like creating GCE connection, uploading GCE image to GCS,
   matching adb devices with consoles, etc
 - it hard to add private VM implementations
   such impl would need to add code to config package
   which would lead to constant merge conflicts
 - interface for VM implementation is mixed with interface for VM users
   this does not allow to provide best interface for both of them
 - there is no way to add common code for all VM implementations

This change solves these problems by:
 - splitting VM interface for users (vm package) and VM interface
   for VM implementations (vmimpl pacakge), this in turn allows
   to add common code
 - adding Pool concept that allows to do global initialization
   and config checking at the right time
 - decoupling manager config from VM-specific config
   each VM type now defines own config

Note: manager configs need to be changed after this change:
VM-specific parts are moved to own "vm" subobject.

Note: this change also drops "local" VM type.
Its story was long unclear and there is now syz-stress which solves the same problem.
2017-06-03 11:31:42 +02:00

80 lines
1.7 KiB
Go

// 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"
"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 || err.Error() != "failed to read from pipe1: EOF" {
t.Fatalf("merger did not produce io.EOF: %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 := string(tee.Bytes()); got != want {
t.Fatalf("bad tee: '%s', want '%s'", got, want)
}
}