fix merge error

main
Ben Grewell 3 years ago
commit afac7be8cd

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/embedded" />

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="fc2840de-29dc-4fca-8e0e-a283562f60ca" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/reporter_darwin.go" afterDir="false" />
@ -44,54 +47,65 @@
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
</component>
<component name="RecentsManager">
<key name="MoveFile.RECENT_KEYS">
<recent name="C:\Users\BGrewell\source\repos\go-iperf\tests\server" />
</key>
<key name="CopyFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$" />
<recent name="C:\Users\BGrewell\source\repos\go-iperf" />
<recent name="C:\Users\BGrewell\repos\go-iperf\embedded" />
</key>
<key name="MoveFile.RECENT_KEYS">
<recent name="C:\Users\BGrewell\source\repos\go-iperf\tests\server" />
</key>
</component>
<component name="RunManager" selected="Go Build.go build github.com/BGrewell/go-iperf/tests/controller">
<configuration name="go build github.com/BGrewell/go-iperf/cmd" type="GoApplicationRunConfiguration" factoryName="Go Application" temporary="true" nameIsGenerated="true">
<module name="go-iperf" />
<working_directory value="$PROJECT_DIR$" />
<kind value="PACKAGE" />
<filePath value="$PROJECT_DIR$/cmd/main.go" />
<package value="github.com/BGrewell/go-iperf/cmd" />
<directory value="$PROJECT_DIR$" />
<filePath value="$PROJECT_DIR$/cmd/main.go" />
<method v="2" />
</configuration>
<configuration name="go build github.com/BGrewell/go-iperf/tests/client" type="GoApplicationRunConfiguration" factoryName="Go Application" temporary="true" nameIsGenerated="true">
<module name="go-iperf" />
<working_directory value="$PROJECT_DIR$" />
<kind value="PACKAGE" />
<filePath value="$PROJECT_DIR$/tests/client/client.go" />
<package value="github.com/BGrewell/go-iperf/tests/client" />
<directory value="$PROJECT_DIR$" />
<filePath value="$PROJECT_DIR$/tests/client/client.go" />
<method v="2" />
</configuration>
<configuration name="go build github.com/BGrewell/go-iperf/tests/controller" type="GoApplicationRunConfiguration" factoryName="Go Application" temporary="true" nameIsGenerated="true">
<module name="go-iperf" />
<working_directory value="$PROJECT_DIR$" />
<kind value="PACKAGE" />
<filePath value="$PROJECT_DIR$/tests/controller/main.go" />
<package value="github.com/BGrewell/go-iperf/tests/controller" />
<directory value="$PROJECT_DIR$" />
<filePath value="$PROJECT_DIR$/tests/controller/main.go" />
<method v="2" />
</configuration>
<configuration name="go build github.com/BGrewell/go-iperf/tests/extract" type="GoApplicationRunConfiguration" factoryName="Go Application" temporary="true" nameIsGenerated="true">
<module name="go-iperf" />
<working_directory value="$PROJECT_DIR$" />
<kind value="PACKAGE" />
<package value="github.com/BGrewell/go-iperf/tests/extract" />
<directory value="$PROJECT_DIR$" />
<filePath value="$PROJECT_DIR$/tests/extract/main.go" />
<method v="2" />
</configuration>
<configuration name="go build github.com/BGrewell/go-iperf/tests/server" type="GoApplicationRunConfiguration" factoryName="Go Application" temporary="true" nameIsGenerated="true">
<module name="go-iperf" />
<working_directory value="$PROJECT_DIR$" />
<kind value="PACKAGE" />
<filePath value="$PROJECT_DIR$/tests/server/server.go" />
<package value="github.com/BGrewell/go-iperf/tests/server" />
<directory value="$PROJECT_DIR$" />
<filePath value="$PROJECT_DIR$/tests/server/server.go" />
<method v="2" />
</configuration>
<recent_temporary>
<list>
<item itemvalue="Go Build.go build github.com/BGrewell/go-iperf/tests/controller" />
<item itemvalue="Go Build.go build github.com/BGrewell/go-iperf/tests/extract" />
<item itemvalue="Go Build.go build github.com/BGrewell/go-iperf/tests/client" />
<item itemvalue="Go Build.go build github.com/BGrewell/go-iperf/tests/server" />
<item itemvalue="Go Build.go build github.com/BGrewell/go-iperf/cmd" />

File diff suppressed because one or more lines are too long

@ -66,6 +66,8 @@ type Client struct {
Running bool `json:"running" yaml:"running" xml:"running"`
Done chan bool `json:"-" yaml:"-" xml:"-"`
Options *ClientOptions `json:"options" yaml:"options" xml:"options"`
Debug bool `json:"-" yaml:"-" xml:"-"`
StdOut bool `json:"-" yaml:"-" xml:"-"`
exitCode *int
report *TestReport
outputStream io.ReadCloser
@ -487,24 +489,27 @@ func (c *Client) SetModeLive() <-chan *StreamIntervalReport {
}
func (c *Client) Start() (err error) {
read := make(chan interface{})
cmd, err := c.commandString()
if err != nil {
return err
}
var exit chan int
c.outputStream, c.errorStream, exit, c.cancel, err = ExecuteAsyncWithCancel(cmd)
c.outputStream, c.errorStream, exit, c.cancel, err = ExecuteAsyncWithCancelReadIndicator(cmd, read)
if err != nil {
return err
}
c.Running = true
//go func() {
// ds := DebugScanner{Silent: false}
// ds := DebugScanner{Silent: !c.StdOut}
// ds.Scan(c.outputStream)
//}()
//go func() {
// ds := DebugScanner{Silent: false}
// ds.Scan(c.errorStream)
//}()
go func() {
ds := DebugScanner{Silent: !c.Debug}
ds.Scan(c.errorStream)
}()
go func() {
var reporter *Reporter
if c.live {
@ -514,11 +519,26 @@ func (c *Client) Start() (err error) {
}
reporter.Start()
} else {
if c.Debug {
fmt.Println("reading output")
}
testOutput, err := ioutil.ReadAll(c.outputStream)
read <- true
if err != nil {
return
if c.Debug {
fmt.Println(err.Error())
}
}
if c.Debug {
fmt.Println("parsing output")
}
c.report, err = Loads(string(testOutput))
if err != nil && c.Debug {
fmt.Println(err.Error())
}
}
if c.Debug {
fmt.Println("complete")
}
exitCode := <-exit
c.exitCode = &exitCode
@ -535,6 +555,5 @@ func (c *Client) Stop() {
if c.Running && c.cancel != nil {
c.cancel()
os.Remove(c.reportingFile)
c.Done <- true
}
}

@ -5,6 +5,7 @@ import (
"fmt"
"log"
"net"
"sync"
"time"
api "github.com/BGrewell/go-iperf/api/go"
@ -16,6 +17,8 @@ func NewController(port int) (controller *Controller, err error) {
Port: port,
clients: make(map[string]*Client),
servers: make(map[string]*Server),
clientLock: sync.Mutex{},
serverLock: sync.Mutex{},
}
err = c.startListener()
@ -30,6 +33,8 @@ type Controller struct {
api.UnimplementedCommandServer
Port int
cmdClient api.CommandClient
clientLock sync.Mutex
serverLock sync.Mutex
clients map[string]*Client
servers map[string]*Server
}
@ -46,7 +51,9 @@ func (c *Controller) GrpcRequestServer(context.Context, *api.StartServerRequest)
return nil, err
}
c.serverLock.Lock()
c.servers[srv.Id] = srv
c.serverLock.Unlock()
reply := &api.StartServerResponse{
Id: srv.Id,
@ -74,6 +81,7 @@ func (c *Controller) startListener() (err error) {
}
}()
time.Sleep(250 * time.Millisecond)
return nil
}
@ -82,13 +90,17 @@ func (c *Controller) NewServer() (server *Server, err error) {
freePort, err := GetUnusedTcpPort()
s := NewServer()
s.SetPort(freePort)
c.serverLock.Lock()
c.servers[s.Id] = s
c.serverLock.Unlock()
return s, nil
}
// StopServer shuts down an iperf server and frees any actively used resources
func (c *Controller) StopServer(id string) (err error) {
c.serverLock.Lock()
delete(c.servers, id)
c.serverLock.Unlock()
return nil
}
@ -100,7 +112,7 @@ func (c *Controller) NewClient(serverAddr string) (client *Client, err error) {
return nil, err
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
ctx, cancel := context.WithTimeout(context.Background(), 2 * time.Second)
defer cancel()
reply, err := grpc.GrpcRequestServer(ctx, &api.StartServerRequest{})
srvPort := int(reply.ListenPort)
@ -108,14 +120,18 @@ func (c *Controller) NewClient(serverAddr string) (client *Client, err error) {
cli := NewClient(serverAddr)
cli.SetPort(srvPort)
c.clientLock.Lock()
c.clients[cli.Id] = cli
c.clientLock.Unlock()
return cli, nil
}
// StopClient will clean up the server side connection and shut down any actively used resources
func (c *Controller) StopClient(id string) (err error) {
c.clientLock.Lock()
delete(c.clients, id)
c.clientLock.Unlock()
return nil
}

@ -43,6 +43,10 @@ func ExecuteAsync(cmd string) (outPipe io.ReadCloser, errPipe io.ReadCloser, exi
}
func ExecuteAsyncWithCancel(cmd string) (stdOut io.ReadCloser, stdErr io.ReadCloser, exitCode chan int, cancelToken context.CancelFunc, err error) {
return ExecuteAsyncWithCancelReadIndicator(cmd, nil)
}
func ExecuteAsyncWithCancelReadIndicator(cmd string, readIndicator chan interface{}) (stdOut io.ReadCloser, stdErr io.ReadCloser, exitCode chan int, cancelToken context.CancelFunc, err error) {
exitCode = make(chan int)
ctx, cancel := context.WithCancel(context.Background())
cmdParts := strings.Fields(cmd)
@ -68,6 +72,11 @@ func ExecuteAsyncWithCancel(cmd string) (stdOut io.ReadCloser, stdErr io.ReadClo
return nil, nil, nil, nil, err
}
go func() {
// Note: Wait() will close the Stdout/Stderr and in some cases can do it before we read. In order to prevent
// this we need to actually wait until the caller has finished reading.
if readIndicator != nil {
<- readIndicator
}
if err := exe.Wait(); err != nil {
if exiterr, ok := err.(*exec.ExitError); ok {
if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {

@ -9,6 +9,7 @@ require (
github.com/golang/protobuf v1.5.2
github.com/google/uuid v1.1.2
github.com/hpcloud/tail v1.0.0 // indirect
github.com/jteeuwen/go-bindata v3.0.7+incompatible // indirect
google.golang.org/grpc v1.36.1
google.golang.org/protobuf v1.26.0
gopkg.in/fsnotify.v1 v1.4.7 // indirect

@ -39,6 +39,8 @@ github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jteeuwen/go-bindata v3.0.7+incompatible h1:91Uy4d9SYVr1kyTJ15wJsog+esAZZl7JmEfTkwmhJts=
github.com/jteeuwen/go-bindata v3.0.7+incompatible/go.mod h1:JVvhzYOiGBnFSYRyV00iY8q7/0PThjIYav1p9h5dmKs=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=

@ -10,7 +10,7 @@ import (
)
var (
Debug = true
Debug = false
binaryDir = ""
binaryLocation = ""
)
@ -22,6 +22,11 @@ func init() {
if err != nil {
log.Fatalf("error initializing iperf: %v", err)
}
} else if runtime.GOOS == "darwin" {
err := extractMacEmbeddedBinaries()
if err != nil {
log.Fatalf("error initializing iperf: %v\n", err)
}
} else {
err := extractLinuxEmbeddedBinaries()
if err != nil {
@ -34,6 +39,13 @@ func Cleanup() {
os.RemoveAll(binaryDir)
}
func ExtractBinaries() (err error) {
files := []string{"cygwin1.dll", "iperf3.exe", "iperf3", "iperf3.app"}
err = extractEmbeddedBinaries(files)
fmt.Printf("files extracted to %s\n", binaryDir)
return err
}
func extractWindowsEmbeddedBinaries() (err error) {
files := []string{"cygwin1.dll", "iperf3.exe"}
err = extractEmbeddedBinaries(files)
@ -48,6 +60,13 @@ func extractLinuxEmbeddedBinaries() (err error) {
return err
}
func extractMacEmbeddedBinaries() (err error) {
files := []string{"iperf3.app"}
err = extractEmbeddedBinaries(files)
binaryLocation = path.Join(binaryDir, "iperf3.app")
return err
}
func extractEmbeddedBinaries(files []string) (err error) {
binaryDir, err = ioutil.TempDir("", "goiperf")
if err != nil {

@ -10,9 +10,47 @@ import (
"time"
)
<<<<<<< HEAD
//TODO: This has not been tested on OS X ... my assumption is it is the exact same as linux but if it's not then the
// reporting will be broken
=======
/*
Connecting to host 10.254.100.100, port 5201
[ 4] local 192.168.3.182 port 54104 connected to 10.254.100.100 port 5201
[ ID] Interval Transfer Bandwidth Retr Cwnd
[ 4] 0.00-1.00 sec 109 MBytes 913 Mbits/sec 13 634 KBytes (omitted)
[ 4] 1.00-2.00 sec 110 MBytes 927 Mbits/sec 7 550 KBytes (omitted)
[ 4] 2.00-3.00 sec 109 MBytes 918 Mbits/sec 6 559 KBytes (omitted)
[ 4] 3.00-4.00 sec 111 MBytes 930 Mbits/sec 6 690 KBytes (omitted)
[ 4] 4.00-5.00 sec 111 MBytes 933 Mbits/sec 0 803 KBytes (omitted)
[ 4] 5.00-6.00 sec 111 MBytes 933 Mbits/sec 6 673 KBytes (omitted)
[ 4] 6.00-7.00 sec 111 MBytes 932 Mbits/sec 6 605 KBytes (omitted)
[ 4] 7.00-8.00 sec 110 MBytes 925 Mbits/sec 0 732 KBytes (omitted)
[ 4] 8.00-9.00 sec 111 MBytes 932 Mbits/sec 0 840 KBytes (omitted)
[ 4] 9.00-10.00 sec 110 MBytes 923 Mbits/sec 6 690 KBytes (omitted)
[ 4] 0.00-1.00 sec 111 MBytes 928 Mbits/sec 6 618 KBytes
[ 4] 1.00-2.00 sec 111 MBytes 931 Mbits/sec 0 745 KBytes
[ 4] 2.00-3.00 sec 111 MBytes 929 Mbits/sec 11 614 KBytes
[ 4] 3.00-4.00 sec 110 MBytes 922 Mbits/sec 6 551 KBytes
[ 4] 4.00-5.00 sec 111 MBytes 933 Mbits/sec 6 519 KBytes
[ 4] 5.00-6.00 sec 111 MBytes 928 Mbits/sec 0 663 KBytes
[ 4] 6.00-7.00 sec 111 MBytes 932 Mbits/sec 0 783 KBytes
[ 4] 7.00-8.00 sec 111 MBytes 933 Mbits/sec 6 656 KBytes
[ 4] 8.00-9.00 sec 111 MBytes 933 Mbits/sec 6 598 KBytes
[ 4] 9.00-10.00 sec 110 MBytes 925 Mbits/sec 0 728 KBytes
[ 4] 10.00-11.00 sec 111 MBytes 933 Mbits/sec 0 839 KBytes
[ 4] 11.00-12.00 sec 109 MBytes 918 Mbits/sec 6 680 KBytes
[ 4] 12.00-12.24 sec 25.0 MBytes 888 Mbits/sec 0 711 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-12.24 sec 1.32 GBytes 928 Mbits/sec 47 sender
[ 4] 0.00-12.24 sec 0.00 Bytes 0.00 bits/sec receiver
iperf Done.
*/
>>>>>>> 8ad71c4c5699a6d55965c2f1ab99d5c306295c3b
func (r *Reporter) runLogProcessor() {
var err error
r.tailer, err = tail.TailFile(r.LogFile, tail.Config{

@ -56,6 +56,9 @@ func (r *Reporter) runLogProcessor() {
if err != nil {
log.Fatalf("failed to tail log file: %v", err)
}
if DEBUG {
log.Printf("starting to watch log file: %s\n", r.LogFile)
}
for {
select {
@ -63,10 +66,16 @@ func (r *Reporter) runLogProcessor() {
if line == nil {
continue
}
if DEBUG {
log.Printf("new line: %s\n", line)
}
if len(line.Text) > 5 {
id := line.Text[1:4]
stream, err := strconv.Atoi(strings.TrimSpace(id))
if err != nil {
if DEBUG {
log.Printf("error converting stream id to int: %v\n", err)
}
continue
}
fields := strings.Fields(line.Text[5:])
@ -117,6 +126,9 @@ func (r *Reporter) runLogProcessor() {
Omitted: omitted,
}
r.ReportingChannel <- report
if DEBUG {
log.Println("added report to reporting channel")
}
}
}
case <-time.After(100 * time.Millisecond):

@ -42,6 +42,8 @@ type Server struct {
Running bool `json:"running" yaml:"running" xml:"running"`
Options *ServerOptions `json:"-" yaml:"-" xml:"-"`
ExitCode *int `json:"exit_code" yaml:"exit_code" xml:"exit_code"`
Debug bool `json:"-" yaml:"-" xml:"-"`
StdOut bool `json:"-" yaml:"-" xml:"-"`
outputStream io.ReadCloser `json:"output_stream" yaml:"output_stream" xml:"output_stream"`
errorStream io.ReadCloser `json:"error_stream" yaml:"error_stream" xml:"error_stream"`
cancel context.CancelFunc `json:"cancel" yaml:"cancel" xml:"cancel"`
@ -79,7 +81,7 @@ func (s *Server) commandString() (cmd string, err error) {
builder.WriteString(" --json")
}
if s.Options.LogFile != nil && s.LogFile() != "" {
if s.Options.LogFile != nil && s.LogFile() != "" {
fmt.Fprintf(&builder, " --logfile %s --forceflush", s.LogFile())
}
@ -159,14 +161,16 @@ func (s *Server) Start() (err error) {
return err
}
s.Running = true
go func() {
ds := DebugScanner{Silent: true}
ds := DebugScanner{Silent: !s.StdOut}
ds.Scan(s.outputStream)
}()
go func() {
ds := DebugScanner{Silent: true}
ds := DebugScanner{Silent: !s.Debug}
ds.Scan(s.errorStream)
}()
go func() {
exitCode := <-exit
s.ExitCode = &exitCode

@ -6,6 +6,10 @@ import (
"io"
)
var (
DEBUG = false
)
type TestMode string
const (

@ -0,0 +1,7 @@
package main
import "github.com/BGrewell/go-iperf"
func main() {
iperf.ExtractBinaries()
}
Loading…
Cancel
Save