diff --git a/net/ping/ping.go b/net/ping/ping.go index 4182d77..10abca5 100644 --- a/net/ping/ping.go +++ b/net/ping/ping.go @@ -6,41 +6,109 @@ import ( "strings" ) -type PingOptions struct { - Retry int - Interval int - Deadline int +type Option interface { + Retry() int + Interval() int + Deadline() int + Validate() } -type Response struct { - TTL int - Time float32 +type Response interface { + TTL() int + Time() float32 } -type Summary struct { - SendCount int - ReceiveCount int - LossPercent float32 - MinTime float32 - MaxTime float32 - AvgTime float32 +type Summary interface { + SendCount() int + ReceiveCount() int + LossPercent() float32 + MinTime() float32 + MaxTime() float32 + AvgTime() float32 +} + +type Result interface { + Responses() map[int]Response + Summary() Summary +} + +type PingOption struct { + retry int + interval int + deadline int +} + +func (o *PingOption) Retry() int { + return o.retry +} +func (o *PingOption) Interval() int { + return o.interval +} +func (o *PingOption) Deadline() int { + return o.deadline +} +func (o *PingOption) Validate() { + if 0 >= o.retry { + o.retry = 1 + } + if 0 >= o.interval { + o.interval = 1 + } + if 0 >= o.deadline { + o.deadline = 1 + } +} + +type PingResponse struct { + ttl int + time float32 +} + +func (r *PingResponse) TTL() int { + return r.ttl +} +func (r *PingResponse) Time() float32 { + return r.time +} + +type PingSummary struct { + sendCount int + receiveCount int + lossPercent float32 + minTime float32 + maxTime float32 + avgTime float32 +} + +func (s *PingSummary) SendCount() int { + return s.sendCount +} +func (s *PingSummary) ReceiveCount() int { + return s.receiveCount +} +func (s *PingSummary) LossPercent() float32 { + return s.lossPercent +} +func (s *PingSummary) MinTime() float32 { + return s.minTime +} +func (s *PingSummary) MaxTime() float32 { + return s.maxTime +} +func (s *PingSummary) AvgTime() float32 { + return s.avgTime } type PingResult struct { - Responses map[int]*Response - Summary *Summary + responses map[int]Response + summary Summary } -func (o *PingOptions) Validate() { - if 0 >= o.Retry { - o.Retry = 1 - } - if 0 >= o.Interval { - o.Interval = 1 - } - if 0 >= o.Deadline { - o.Deadline = 1 - } +func (r *PingResult) Responses() map[int]Response { + return r.responses +} +func (r *PingResult) Summary() Summary { + return r.summary } // $ ping 192.168.1.1 -c 7 -i 1 -w 0.3 @@ -54,10 +122,10 @@ func (o *PingOptions) Validate() { // --- 192.168.1.1 ping statistics --- // 7 packets transmitted, 4 received, 42% packet loss, time 6010ms // rtt min/avg/max/mdev = 0.163/0.253/0.344/0.082 ms -func parseLinuxPing(output []byte) (*PingResult, error) { +func parseLinuxPing(output []byte) (Result, error) { result := &PingResult{ - Responses: make(map[int]*Response, 0), - Summary: &Summary{}, + responses: make(map[int]Response, 0), + summary: &PingSummary{}, } lines := strings.Split(string(output), "\n") @@ -77,21 +145,21 @@ LOOP: log.Print(err) continue LOOP } - result.Summary.MinTime = float32(minTime) + result.summary.(*PingSummary).minTime = float32(minTime) maxTime, err := strconv.ParseFloat(times[2], 32) if nil != err { log.Print(err) continue LOOP } - result.Summary.MaxTime = float32(maxTime) + result.summary.(*PingSummary).maxTime = float32(maxTime) avgTime, err := strconv.ParseFloat(times[1], 32) if nil != err { log.Print(err) continue LOOP } - result.Summary.AvgTime = float32(avgTime) + result.summary.(*PingSummary).avgTime = float32(avgTime) case 8: if "bytes" != fields[1] || "from" != fields[2] { @@ -117,9 +185,9 @@ LOOP: continue LOOP } - result.Responses[seq] = &Response{ - TTL: ttl, - Time: float32(_time), + result.responses[seq] = &PingResponse{ + ttl: ttl, + time: float32(_time), } case 10: @@ -128,21 +196,21 @@ LOOP: log.Print(err) continue LOOP } - result.Summary.SendCount = sendCount + result.summary.(*PingSummary).sendCount = sendCount receiveCount, err := strconv.Atoi(fields[3]) if nil != err { log.Print(err) continue LOOP } - result.Summary.ReceiveCount = receiveCount + result.summary.(*PingSummary).receiveCount = receiveCount lossPercent, err := strconv.ParseFloat(strings.Replace(fields[5], "%", "", -1), 32) if nil != err { log.Print(err) continue LOOP } - result.Summary.LossPercent = float32(lossPercent) + result.summary.(*PingSummary).lossPercent = float32(lossPercent) } } @@ -178,10 +246,10 @@ LOOP: // Approximate round trip times in milli-seconds: // Minimum = 37ms, Maximum = 38ms, Average = 37ms -func parseWindowsPing(output []byte) (*PingResult, error) { +func parseWindowsPing(output []byte) (Result, error) { result := &PingResult{ - Responses: make(map[int]*Response, 0), - Summary: &Summary{}, + responses: make(map[int]Response, 0), + summary: &PingSummary{}, } lines := strings.Split(string(output), "\n") @@ -218,9 +286,9 @@ LOOP: continue LOOP } - result.Responses[seq] = &Response{ - TTL: ttl, - Time: float32(_time), + result.responses[seq] = &PingResponse{ + ttl: ttl, + time: float32(_time), } seq = seq + 1 case 9: @@ -235,7 +303,7 @@ LOOP: log.Print(err) continue LOOP } - result.Summary.MinTime = float32(minTime) + result.summary.(*PingSummary).minTime = float32(minTime) maxTimes := strings.Replace(fields[5], "ms", "", -1) maxTimes = strings.Replace(maxTimes, ",", "", -1) @@ -244,7 +312,7 @@ LOOP: log.Print(err) continue LOOP } - result.Summary.MaxTime = float32(maxTime) + result.summary.(*PingSummary).maxTime = float32(maxTime) avgTimes := strings.Replace(fields[8], "ms", "", -1) avgTime, err := strconv.ParseFloat(avgTimes, 32) @@ -252,7 +320,7 @@ LOOP: log.Print(err) continue LOOP } - result.Summary.AvgTime = float32(avgTime) + result.summary.(*PingSummary).avgTime = float32(avgTime) case 12: if "Packets:" != fields[0] { @@ -263,14 +331,14 @@ LOOP: log.Print(err) continue LOOP } - result.Summary.SendCount = sendCount + result.summary.(*PingSummary).sendCount = sendCount receiveCount, err := strconv.Atoi(strings.Replace(fields[6], ",", "", -1)) if nil != err { log.Print(err) continue LOOP } - result.Summary.ReceiveCount = receiveCount + result.summary.(*PingSummary).receiveCount = receiveCount lossPercents := strings.Replace(fields[10], "(", "", -1) lossPercents = strings.Replace(lossPercents, "%", "", -1) @@ -279,7 +347,7 @@ LOOP: log.Print(err) continue LOOP } - result.Summary.LossPercent = float32(lossPercent) + result.summary.(*PingSummary).lossPercent = float32(lossPercent) } } @@ -297,10 +365,10 @@ LOOP: // --- 192.168.1.1 ping statistics --- // 5 packets transmitted, 5 packets received, 0.0% packet loss // round-trip min/avg/max/stddev = 0.971/2.760/3.934/1.204 ms -func parseDarwinPing(output []byte) (*PingResult, error) { +func parseDarwinPing(output []byte) (Result, error) { result := &PingResult{ - Responses: make(map[int]*Response, 0), - Summary: &Summary{}, + responses: make(map[int]Response, 0), + summary: &PingSummary{}, } lines := strings.Split(string(output), "\n") @@ -320,21 +388,21 @@ LOOP: log.Print(err) continue LOOP } - result.Summary.MinTime = float32(minTime) + result.summary.(*PingSummary).minTime = float32(minTime) maxTime, err := strconv.ParseFloat(times[2], 32) if nil != err { log.Print(err) continue LOOP } - result.Summary.MaxTime = float32(maxTime) + result.summary.(*PingSummary).maxTime = float32(maxTime) avgTime, err := strconv.ParseFloat(times[1], 32) if nil != err { log.Print(err) continue LOOP } - result.Summary.AvgTime = float32(avgTime) + result.summary.(*PingSummary).avgTime = float32(avgTime) case 8: if "bytes" != fields[1] || "from" != fields[2] { @@ -360,9 +428,9 @@ LOOP: continue LOOP } - result.Responses[seq] = &Response{ - TTL: ttl, - Time: float32(_time), + result.responses[seq] = &PingResponse{ + ttl: ttl, + time: float32(_time), } case 9: @@ -371,21 +439,21 @@ LOOP: log.Print(err) continue LOOP } - result.Summary.SendCount = sendCount + result.summary.(*PingSummary).sendCount = sendCount receiveCount, err := strconv.Atoi(fields[3]) if nil != err { log.Print(err) continue LOOP } - result.Summary.ReceiveCount = receiveCount + result.summary.(*PingSummary).receiveCount = receiveCount lossPercent, err := strconv.ParseFloat(strings.Replace(fields[6], "%", "", -1), 32) if nil != err { log.Print(err) continue LOOP } - result.Summary.LossPercent = float32(lossPercent) + result.summary.(*PingSummary).lossPercent = float32(lossPercent) } } diff --git a/net/ping/ping_darwin.go b/net/ping/ping_darwin.go index 124d030..ca91688 100644 --- a/net/ping/ping_darwin.go +++ b/net/ping/ping_darwin.go @@ -5,13 +5,13 @@ import ( "os/exec" ) -func Ping(destination string, options *PingOptions) (*PingResult, error) { - options.Validate() +func Ping(destination string, options Option) (Result, error) { + option.Validate() params := make([]string, 0) params = append(params, destination) - params = append(params, fmt.Sprintf("-c %d", options.Retry)) - params = append(params, fmt.Sprintf("-i %d", options.Interval)) + params = append(params, fmt.Sprintf("-c %d", option.Retry())) + params = append(params, fmt.Sprintf("-i %d", option.Interval())) pCmd := exec.Command("ping", params...) output, err := pCmd.CombinedOutput() diff --git a/net/ping/ping_darwin_test.go b/net/ping/ping_darwin_test.go index b4deece..e9d8cf9 100644 --- a/net/ping/ping_darwin_test.go +++ b/net/ping/ping_darwin_test.go @@ -8,27 +8,27 @@ import ( func TestPing(t *testing.T) { type args struct { destination string - options *PingOptions + option Option } tests := []struct { name string args args - want *PingResult + want Result wantErr bool }{ { name: "192.168.1.1", args: args{ destination: "192.168.1.1", - options: &PingOptions{ - Retry: 4, + option: &PingOption{ + retry: 4, }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := Ping(tt.args.destination, tt.args.options) + got, err := Ping(tt.args.destination, tt.args.option) if (err != nil) != tt.wantErr { t.Errorf("Ping() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/net/ping/ping_linux.go b/net/ping/ping_linux.go index 1578270..5f79380 100644 --- a/net/ping/ping_linux.go +++ b/net/ping/ping_linux.go @@ -2,21 +2,23 @@ package ping import ( "fmt" + "log" "os/exec" ) -func Ping(destination string, options *PingOptions) (*PingResult, error) { - options.Validate() +func Ping(destination string, option Option) (Result, error) { + option.Validate() params := make([]string, 0) params = append(params, destination) - params = append(params, fmt.Sprintf("-c %d", options.Retry)) - params = append(params, fmt.Sprintf("-i %d", options.Interval)) - params = append(params, fmt.Sprintf("-w %d", options.Deadline)) + params = append(params, fmt.Sprintf("-c %d", option.Retry())) + params = append(params, fmt.Sprintf("-i %d", option.Interval())) pCmd := exec.Command("ping", params...) + log.Print(pCmd.Args) output, err := pCmd.CombinedOutput() if err != nil { + log.Print(err) return nil, err } diff --git a/net/ping/ping_linux_test.go b/net/ping/ping_linux_test.go index 4ea5306..516017a 100644 --- a/net/ping/ping_linux_test.go +++ b/net/ping/ping_linux_test.go @@ -5,27 +5,27 @@ import "testing" func TestPing(t *testing.T) { type args struct { destination string - options *PingOptions + option Option } tests := []struct { name string args args - want *PingResult + want Result wantErr bool }{ { name: "192.168.1.1", args: args{ destination: "192.168.1.1", - options: &PingOptions{ - Retry: 4, + option: &PingOption{ + retry: 4, }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := Ping(tt.args.destination, tt.args.options) + got, err := Ping(tt.args.destination, tt.args.option) if (err != nil) != tt.wantErr { t.Errorf("Ping() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/net/ping/ping_test.go b/net/ping/ping_test.go index 366c70b..0240849 100644 --- a/net/ping/ping_test.go +++ b/net/ping/ping_test.go @@ -17,12 +17,13 @@ func TestPingOptions_Validate(t *testing.T) { }{ // TODO: Add test cases. } + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - o := &PingOptions{ - Retry: tt.fields.Retry, - Interval: tt.fields.Interval, - Deadline: tt.fields.Deadline, + o := &PingOption{ + retry: tt.fields.Retry, + interval: tt.fields.Interval, + deadline: tt.fields.Deadline, } o.Validate() }) @@ -62,7 +63,7 @@ func Test_parseWindowsPing(t *testing.T) { tests := []struct { name string args args - want *PingResult + want Result wantErr bool }{ { @@ -108,7 +109,7 @@ func Test_parseDarwinPing(t *testing.T) { tests := []struct { name string args args - want *PingResult + want Result wantErr bool }{ { diff --git a/net/ping/ping_windows.go b/net/ping/ping_windows.go index 6f8e605..fb89cbd 100644 --- a/net/ping/ping_windows.go +++ b/net/ping/ping_windows.go @@ -5,12 +5,12 @@ import ( "os/exec" ) -func Ping(destination string, options *PingOptions) (*PingResult, error) { - options.Validate() +func Ping(destination string, option Option) (Result, error) { + option.Validate() params := make([]string, 0) params = append(params, "/C") - params = append(params, fmt.Sprintf("chcp 437 && ping %s -n %d -w %d", destination, options.Retry, options.Deadline*1000)) + params = append(params, fmt.Sprintf("chcp 437 && ping %s -n %d -w %d", destination, option.Retry(), option.Deadline()*1000)) pCmd := exec.Command("cmd.exe", params...) output, err := pCmd.CombinedOutput() diff --git a/net/ping/ping_windows_test.go b/net/ping/ping_windows_test.go index 4ea5306..516017a 100644 --- a/net/ping/ping_windows_test.go +++ b/net/ping/ping_windows_test.go @@ -5,27 +5,27 @@ import "testing" func TestPing(t *testing.T) { type args struct { destination string - options *PingOptions + option Option } tests := []struct { name string args args - want *PingResult + want Result wantErr bool }{ { name: "192.168.1.1", args: args{ destination: "192.168.1.1", - options: &PingOptions{ - Retry: 4, + option: &PingOption{ + retry: 4, }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := Ping(tt.args.destination, tt.args.options) + got, err := Ping(tt.args.destination, tt.args.option) if (err != nil) != tt.wantErr { t.Errorf("Ping() error = %v, wantErr %v", err, tt.wantErr) return