Skip to content

Commit

Permalink
Merge e1408ad into db6ef3f
Browse files Browse the repository at this point in the history
  • Loading branch information
robertodauria committed Feb 12, 2020
2 parents db6ef3f + e1408ad commit 324fda6
Show file tree
Hide file tree
Showing 9 changed files with 338 additions and 79 deletions.
54 changes: 30 additions & 24 deletions cmd/ndt7-client/internal/emitter/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,34 @@ import (
"io"
"os"

"github.com/m-lab/ndt7-client-go/cmd/ndt7-client/internal"
"github.com/m-lab/ndt7-client-go/spec"
)

// Batch is a batch emitter. It emits messages consistent with
// the cmd/ndt7-client/main.go documentation for `-batch`.
type Batch struct {
// JSON is a JSON emitter. It emits messages consistent with
// the cmd/ndt7-client/main.go documentation for `-format=json`.
type JSON struct {
io.Writer
}

// NewBatch creates a new batch emitter
func NewBatch() Batch {
return Batch{
// NewJSON creates a new JSON emitter
func NewJSON() JSON {
return JSON{
Writer: os.Stdout,
}
}

func (b Batch) emitData(data []byte) error {
_, err := b.Write(append(data, byte('\n')))
func (j JSON) emitData(data []byte) error {
_, err := j.Write(append(data, byte('\n')))
return err
}

func (b Batch) emitInterface(any interface{}) error {
func (j JSON) emitInterface(any interface{}) error {
data, err := json.Marshal(any)
if err != nil {
return err
}
return b.emitData(data)
return j.emitData(data)
}

type batchEvent struct {
Expand All @@ -46,8 +47,8 @@ type batchValue struct {
}

// OnStarting emits the starting event
func (b Batch) OnStarting(test spec.TestKind) error {
return b.emitInterface(batchEvent{
func (j JSON) OnStarting(test spec.TestKind) error {
return j.emitInterface(batchEvent{
Key: "starting",
Value: batchValue{
Measurement: spec.Measurement{
Expand All @@ -58,50 +59,50 @@ func (b Batch) OnStarting(test spec.TestKind) error {
}

// OnError emits the error event
func (b Batch) OnError(test spec.TestKind, err error) error {
return b.emitInterface(batchEvent{
func (j JSON) OnError(test spec.TestKind, err error) error {
return j.emitInterface(batchEvent{
Key: "error",
Value: batchValue{
Measurement: spec.Measurement{
Test: test,
Test: test,
},
Failure: err.Error(),
},
})
}

// OnConnected emits the connected event
func (b Batch) OnConnected(test spec.TestKind, fqdn string) error {
return b.emitInterface(batchEvent{
func (j JSON) OnConnected(test spec.TestKind, fqdn string) error {
return j.emitInterface(batchEvent{
Key: "connected",
Value: batchValue{
Measurement: spec.Measurement{
Test: test,
Test: test,
},
Server: fqdn,
},
})
}

// OnDownloadEvent handles an event emitted during the download
func (b Batch) OnDownloadEvent(m *spec.Measurement) error {
return b.emitInterface(batchEvent{
func (j JSON) OnDownloadEvent(m *spec.Measurement) error {
return j.emitInterface(batchEvent{
Key: "measurement",
Value: m,
})
}

// OnUploadEvent handles an event emitted during the upload
func (b Batch) OnUploadEvent(m *spec.Measurement) error {
return b.emitInterface(batchEvent{
func (j JSON) OnUploadEvent(m *spec.Measurement) error {
return j.emitInterface(batchEvent{
Key: "measurement",
Value: m,
})
}

// OnComplete is the event signalling the end of the test
func (b Batch) OnComplete(test spec.TestKind) error {
return b.emitInterface(batchEvent{
func (j JSON) OnComplete(test spec.TestKind) error {
return j.emitInterface(batchEvent{
Key: "complete",
Value: batchValue{
Measurement: spec.Measurement{
Expand All @@ -110,3 +111,8 @@ func (b Batch) OnComplete(test spec.TestKind) error {
},
})
}

// OnSummary handles the summary event, emitted after the test is over.
func (j JSON) OnSummary(s *internal.Summary) error {
return j.emitInterface(s)
}
84 changes: 42 additions & 42 deletions cmd/ndt7-client/internal/emitter/batch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import (
"github.com/m-lab/ndt7-client-go/spec"
)

func TestBatchOnStarting(t *testing.T) {
func TestJSONOnStarting(t *testing.T) {
sw := &mocks.SavingWriter{}
batch := Batch{sw}
err := batch.OnStarting("download")
j := JSON{sw}
err := j.OnStarting("download")
if err != nil {
t.Fatal(err)
}
Expand All @@ -38,18 +38,18 @@ func TestBatchOnStarting(t *testing.T) {
}
}

func TestBatchOnStartingFailure(t *testing.T) {
batch := Batch{&mocks.FailingWriter{}}
err := batch.OnStarting("download")
func TestJSONOnStartingFailure(t *testing.T) {
j := JSON{&mocks.FailingWriter{}}
err := j.OnStarting("download")
if err != mocks.ErrMocked {
t.Fatal("Not the error we expected")
}
}

func TestBatchOnError(t *testing.T) {
func TestJSONOnError(t *testing.T) {
sw := &mocks.SavingWriter{}
batch := Batch{sw}
err := batch.OnError("download", errors.New("mocked error"))
j := JSON{sw}
err := j.OnError("download", errors.New("mocked error"))
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -78,18 +78,18 @@ func TestBatchOnError(t *testing.T) {
}
}

func TestBatchOnErrorFailure(t *testing.T) {
batch := Batch{&mocks.FailingWriter{}}
err := batch.OnError("download", errors.New("some error"))
func TestJSONOnErrorFailure(t *testing.T) {
bajch := JSON{&mocks.FailingWriter{}}
err := bajch.OnError("download", errors.New("some error"))
if err != mocks.ErrMocked {
t.Fatal("Not the error we expected")
}
}

func TestBatchOnConnected(t *testing.T) {
func TestJSONOnConnected(t *testing.T) {
sw := &mocks.SavingWriter{}
batch := Batch{sw}
err := batch.OnConnected("download", "FQDN")
j := JSON{sw}
err := j.OnConnected("download", "FQDN")
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -118,18 +118,18 @@ func TestBatchOnConnected(t *testing.T) {
}
}

func TestBatchOnConnectedFailure(t *testing.T) {
batch := Batch{&mocks.FailingWriter{}}
err := batch.OnConnected("download", "FQDN")
func TestJSONOnConnectedFailure(t *testing.T) {
j := JSON{&mocks.FailingWriter{}}
err := j.OnConnected("download", "FQDN")
if err != mocks.ErrMocked {
t.Fatal("Not the error we expected")
}
}

func TestBatchOnDownloadEvent(t *testing.T) {
func TestJSONOnDownloadEvent(t *testing.T) {
sw := &mocks.SavingWriter{}
batch := Batch{sw}
err := batch.OnDownloadEvent(&spec.Measurement{
j := JSON{sw}
err := j.OnDownloadEvent(&spec.Measurement{
AppInfo: &spec.AppInfo{
ElapsedTime: 7100000,
NumBytes: 41000,
Expand Down Expand Up @@ -175,18 +175,18 @@ func TestBatchOnDownloadEvent(t *testing.T) {
}
}

func TestBatchOnDownloadEventFailure(t *testing.T) {
batch := Batch{&mocks.FailingWriter{}}
err := batch.OnDownloadEvent(&spec.Measurement{})
func TestJSONOnDownloadEventFailure(t *testing.T) {
j := JSON{&mocks.FailingWriter{}}
err := j.OnDownloadEvent(&spec.Measurement{})
if err != mocks.ErrMocked {
t.Fatal("Not the error we expected")
}
}

func TestBatchOnUploadEvent(t *testing.T) {
func TestJSONOnUploadEvent(t *testing.T) {
sw := &mocks.SavingWriter{}
batch := Batch{sw}
err := batch.OnUploadEvent(&spec.Measurement{
j := JSON{sw}
err := j.OnUploadEvent(&spec.Measurement{
AppInfo: &spec.AppInfo{
ElapsedTime: 3000000,
NumBytes: 100000000,
Expand Down Expand Up @@ -232,18 +232,18 @@ func TestBatchOnUploadEvent(t *testing.T) {
}
}

func TestBatchOnUploadEventFailure(t *testing.T) {
batch := Batch{&mocks.FailingWriter{}}
err := batch.OnUploadEvent(&spec.Measurement{})
func TestJSONOnUploadEventFailure(t *testing.T) {
j := JSON{&mocks.FailingWriter{}}
err := j.OnUploadEvent(&spec.Measurement{})
if err != mocks.ErrMocked {
t.Fatal("Not the error we expected")
}
}

func TestBatchOnComplete(t *testing.T) {
func TestJSONOnComplete(t *testing.T) {
sw := &mocks.SavingWriter{}
batch := Batch{sw}
err := batch.OnComplete("download")
j := JSON{sw}
err := j.OnComplete("download")
if err != nil {
t.Fatal(err)
}
Expand All @@ -268,28 +268,28 @@ func TestBatchOnComplete(t *testing.T) {
}
}

func TestBatchOnCompleteFailure(t *testing.T) {
batch := Batch{&mocks.FailingWriter{}}
err := batch.OnComplete("download")
func TestJSONOnCompleteFailure(t *testing.T) {
j := JSON{&mocks.FailingWriter{}}
err := j.OnComplete("download")
if err != mocks.ErrMocked {
t.Fatal("Not the error we expected")
}
}

func TestNewBatchConstructor(t *testing.T) {
batch := NewBatch()
if batch.Writer != os.Stdout {
t.Fatal("Batch is not using stdout")
func TestNewJSONConstructor(t *testing.T) {
j := NewJSON()
if j.Writer != os.Stdout {
t.Fatal("JSON is not using stdout")
}
}

func TestEmitInterfaceFailure(t *testing.T) {
batch := NewBatch()
j := NewJSON()
// See https://stackoverflow.com/a/48901259
x := map[string]interface{}{
"foo": make(chan int),
}
err := batch.emitInterface(x)
err := j.emitInterface(x)
switch err.(type) {
case *json.UnsupportedTypeError:
// nothing
Expand Down
8 changes: 7 additions & 1 deletion cmd/ndt7-client/internal/emitter/emitter.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// Package emitter contains the ndt7-client emitter.
package emitter

import "github.com/m-lab/ndt7-client-go/spec"
import (
"github.com/m-lab/ndt7-client-go/cmd/ndt7-client/internal"
"github.com/m-lab/ndt7-client-go/spec"
)

// Emitter is a generic emitter. When an event occurs, the
// corresponding method will be called. An error will generally
Expand Down Expand Up @@ -29,4 +32,7 @@ type Emitter interface {

// OnComplete is always emitted when the test is over.
OnComplete(test spec.TestKind) error

// OnSummary is emitted after the test is over.
OnSummary(s *internal.Summary) error
}
40 changes: 40 additions & 0 deletions cmd/ndt7-client/internal/emitter/interactive.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"io"
"os"

"github.com/m-lab/ndt7-client-go/cmd/ndt7-client/internal"

"github.com/m-lab/ndt7-client-go/spec"
)

Expand Down Expand Up @@ -69,3 +71,41 @@ func (i Interactive) OnComplete(test spec.TestKind) error {
_, err := fmt.Fprintf(i.out, "\n%s: complete\n", test)
return err
}

// OnSummary handles the summary event.
func (i Interactive) OnSummary(s *internal.Summary) error {
_, err := fmt.Fprintf(i.out, "%15s: %s\n", "Server", s.Server)
if err != nil {
return err
}

_, err = fmt.Fprintf(i.out, "%15s: %s\n", "Client", s.Client)
if err != nil {
return err
}

_, err = fmt.Fprintf(i.out, "%15s: %7.1f %s\n", "Latency", s.RTT.Value, s.RTT.Unit)
if err != nil {
return err
}

_, err = fmt.Fprintf(i.out, "%15s: %7.1f %s\n", "Download",
s.Download.Value, s.Upload.Unit)
if err != nil {
return err
}

_, err = fmt.Fprintf(i.out, "%15s: %7.1f %s\n", "Upload", s.Upload.Value,
s.Upload.Unit)
if err != nil {
return err
}

_, err = fmt.Fprintf(i.out, "%15s: %7.2f %s\n", "Retransmission",
s.DownloadRetrans.Value, s.DownloadRetrans.Unit)
if err != nil {
return err
}

return nil
}
Loading

0 comments on commit 324fda6

Please sign in to comment.