[dev_finder] add tests for the `resolve` command
Also there's some code shuffling for better code reuse.
Bug: DX-1402 #comment
Change-Id: I107fa890607817e2ab5bd3e0f9dbf9462ebeed87
diff --git a/cmd/dev_finder/common.go b/cmd/dev_finder/common.go
index 975179f..1a3288e 100644
--- a/cmd/dev_finder/common.go
+++ b/cmd/dev_finder/common.go
@@ -5,6 +5,7 @@
import (
"context"
+ "encoding/json"
"errors"
"flag"
"fmt"
@@ -188,3 +189,30 @@
// Device domain name. Can be omitted.
Domain string `json:"domain,omitempty"`
}
+
+func (cmd *devFinderCmd) outputNormal(filteredDevices []*fuchsiaDevice, includeDomain bool) error {
+ for _, device := range filteredDevices {
+ if includeDomain {
+ fmt.Fprintf(cmd.Output(), "%v %v\n", device.addr, device.domain)
+ } else {
+ fmt.Fprintf(cmd.Output(), "%v\n", device.addr)
+ }
+ }
+ return nil
+}
+
+func (cmd *devFinderCmd) outputJSON(filteredDevices []*fuchsiaDevice, includeDomain bool) error {
+ jsonOut := jsonOutput{Devices: make([]jsonDevice, 0, len(filteredDevices))}
+
+ for _, device := range filteredDevices {
+ dev := jsonDevice{Addr: device.addr.String()}
+ if includeDomain {
+ dev.Domain = device.domain
+ }
+ jsonOut.Devices = append(jsonOut.Devices, dev)
+ }
+
+ e := json.NewEncoder(cmd.Output())
+ e.SetIndent("", " ")
+ return e.Encode(jsonOut)
+}
diff --git a/cmd/dev_finder/dev_finder_test.go b/cmd/dev_finder/dev_finder_test.go
index e96641d..6487491 100644
--- a/cmd/dev_finder/dev_finder_test.go
+++ b/cmd/dev_finder/dev_finder_test.go
@@ -30,37 +30,60 @@
func (m *fakeMDNS) AddWarningHandler(func(net.Addr, error)) {}
func (m *fakeMDNS) AddErrorHandler(func(error)) {}
func (m *fakeMDNS) SendTo(mdns.Packet, *net.UDPAddr) error { return nil }
-func (m *fakeMDNS) Send(mdns.Packet) error { return nil }
-func (m *fakeMDNS) Start(context.Context, int) error {
+func (m *fakeMDNS) Send(packet mdns.Packet) error {
if m.answer != nil {
- ifc := net.Interface{}
- ip := net.IPAddr{IP: net.ParseIP(m.answer.ip)}
- answers := make([]mdns.Record, len(m.answer.domains))
- for _, d := range m.answer.domains {
- data := make([]byte, len(d)+1)
- data[0] = byte(len(d))
- copy(data[1:], []byte(d))
- answers = append(answers, mdns.Record{
- Class: mdns.IN,
- Type: mdns.PTR,
- Data: data,
- })
- }
- pkt := mdns.Packet{Answers: answers}
go func() {
- for _, h := range m.handlers {
- h(ifc, &ip, pkt)
+ ifc := net.Interface{}
+ ip := net.IPAddr{IP: net.ParseIP(m.answer.ip).To4()}
+ for _, q := range packet.Questions {
+ switch {
+ case q.Type == mdns.PTR && q.Class == mdns.IN:
+ // 'list' command
+ answers := make([]mdns.Record, len(m.answer.domains))
+ for _, d := range m.answer.domains {
+ data := make([]byte, len(d)+1)
+ data[0] = byte(len(d))
+ copy(data[1:], []byte(d))
+ answers = append(answers, mdns.Record{
+ Class: mdns.IN,
+ Type: mdns.PTR,
+ Data: data,
+ })
+ }
+ pkt := mdns.Packet{Answers: answers}
+ for _, h := range m.handlers {
+ h(ifc, &ip, pkt)
+ }
+ case q.Type == mdns.A && q.Class == mdns.IN:
+ // 'resolve' command
+ answers := make([]mdns.Record, len(m.answer.domains))
+ for _, d := range m.answer.domains {
+ answers = append(answers, mdns.Record{
+ Class: mdns.IN,
+ Type: mdns.A,
+ Data: net.ParseIP(m.answer.ip).To4(),
+ Domain: d,
+ })
+ }
+ pkt := mdns.Packet{Answers: answers}
+ for _, h := range m.handlers {
+ h(ifc, &ip, pkt)
+ }
+ }
}
}()
}
return nil
}
+func (m *fakeMDNS) Start(context.Context, int) error { return nil }
func compareFuchsiaDevices(d1, d2 *fuchsiaDevice) bool {
return cmp.Equal(d1.addr, d2.addr) && cmp.Equal(d1.domain, d2.domain)
}
-func TestListFindDevices(t *testing.T) {
+//// Tests for the `list` command.
+
+func TestListDevices(t *testing.T) {
// Because mdnsPorts have two ports specified, two MDNS objects are
// created. To emulate the case where only one port responds, create
// only one fake MDNS object with answers. The other one wouldn't
@@ -70,7 +93,7 @@
devFinderCmd: devFinderCmd{
mdnsHandler: listMDNSHandler,
mdnsPorts: "5353,5356",
- timeout: 2000,
+ timeout: 10,
newMDNSFunc: func() mdnsInterface {
mdnsCount++
switch mdnsCount {
@@ -91,27 +114,27 @@
},
}
- got, err := cmd.findDevices(context.Background())
+ got, err := cmd.listDevices(context.Background())
if err != nil {
- t.Fatalf("findDevices: %v", err)
+ t.Fatalf("listDevices: %v", err)
}
want := []*fuchsiaDevice{
{
- addr: net.ParseIP("192.168.0.42"),
+ addr: net.ParseIP("192.168.0.42").To4(),
domain: "some.domain",
},
{
- addr: net.ParseIP("192.168.0.42"),
+ addr: net.ParseIP("192.168.0.42").To4(),
domain: "another.domain",
},
}
if d := cmp.Diff(want, got, cmp.Comparer(compareFuchsiaDevices)); d != "" {
- t.Errorf("findDevices mismatch: (-want +got):\n%s", d)
+ t.Errorf("listDevices mismatch: (-want +got):\n%s", d)
}
}
-func TestListFindDevices_domainFilter(t *testing.T) {
+func TestListDevices_domainFilter(t *testing.T) {
// Because mdnsPorts have two ports specified, two MDNS objects are
// created. To emulate the case where only one port responds, create
// only one fake MDNS object with answers. The other one wouldn't
@@ -121,7 +144,7 @@
devFinderCmd: devFinderCmd{
mdnsHandler: listMDNSHandler,
mdnsPorts: "5353,5356",
- timeout: 2000,
+ timeout: 10,
newMDNSFunc: func() mdnsInterface {
mdnsCount++
switch mdnsCount {
@@ -143,148 +166,180 @@
domainFilter: "some",
}
- got, err := cmd.findDevices(context.Background())
+ got, err := cmd.listDevices(context.Background())
if err != nil {
- t.Fatalf("findDevices: %v", err)
+ t.Fatalf("listDevices: %v", err)
}
want := []*fuchsiaDevice{
{
- addr: net.ParseIP("192.168.0.42"),
+ addr: net.ParseIP("192.168.0.42").To4(),
domain: "some.domain",
},
}
if d := cmp.Diff(want, got, cmp.Comparer(compareFuchsiaDevices)); d != "" {
- t.Errorf("findDevices mismatch: (-want +got):\n%s", d)
+ t.Errorf("listDevices mismatch: (-want +got):\n%s", d)
}
}
-func TestListOutputNormal(t *testing.T) {
+//// Tests for the `resolve` command.
+
+func TestResolveDevices(t *testing.T) {
+ // Because mdnsPorts have two ports specified, two MDNS objects are
+ // created. To emulate the case where only one port responds, create
+ // only one fake MDNS object with answers. The other one wouldn't
+ // respond at all. See the Start() method above.
+ mdnsCount := 0
+ cmd := resolveCmd{
+ devFinderCmd: devFinderCmd{
+ mdnsHandler: resolveMDNSHandler,
+ mdnsPorts: "5353,5356",
+ timeout: 10,
+ newMDNSFunc: func() mdnsInterface {
+ mdnsCount++
+ switch mdnsCount {
+ case 1:
+ return &fakeMDNS{
+ answer: &fakeAnswer{
+ ip: "192.168.0.42",
+ domains: []string{
+ "some.domain.local",
+ "another.domain.local",
+ },
+ },
+ }
+ default:
+ return &fakeMDNS{}
+ }
+ },
+ },
+ }
+
+ got, err := cmd.resolveDevices(context.Background(), "some.domain")
+ if err != nil {
+ t.Fatalf("resolveDevices: %v", err)
+ }
+ want := []*fuchsiaDevice{
+ {
+ addr: net.ParseIP("192.168.0.42").To4(),
+ domain: "some.domain.local",
+ },
+ }
+ if d := cmp.Diff(want, got, cmp.Comparer(compareFuchsiaDevices)); d != "" {
+ t.Errorf("resolveDevices mismatch: (-want +got):\n%s", d)
+ }
+
+}
+
+//// Tests for output functions.
+
+func TestOutputNormal(t *testing.T) {
devs := []*fuchsiaDevice{
{
- addr: net.ParseIP("123.12.234.23"),
+ addr: net.ParseIP("123.12.234.23").To4(),
+ domain: "hello.world",
},
{
- addr: net.ParseIP("11.22.33.44"),
+ addr: net.ParseIP("11.22.33.44").To4(),
+ domain: "fuchsia.rocks",
},
}
- var buf strings.Builder
- cmd := listCmd{
- devFinderCmd: devFinderCmd{output: &buf},
- }
- cmd.outputNormal(devs)
- got := buf.String()
- want := `123.12.234.23
+ {
+ var buf strings.Builder
+ cmd := devFinderCmd{output: &buf}
+
+ cmd.outputNormal(devs, false)
+
+ got := buf.String()
+ want := `123.12.234.23
11.22.33.44
`
- if d := cmp.Diff(want, got); d != "" {
- t.Errorf("outputNormal mismatch: (-want +got):\n%s", d)
+ if d := cmp.Diff(want, got); d != "" {
+ t.Errorf("outputNormal mismatch: (-want +got):\n%s", d)
+ }
}
-}
-func TestListOutputNormal_fullInfo(t *testing.T) {
- devs := []*fuchsiaDevice{
- {
- addr: net.ParseIP("123.12.234.23"),
- domain: "hello.world",
- },
- {
- addr: net.ParseIP("11.22.33.44"),
- domain: "fuchsia.rocks",
- },
- }
- var buf strings.Builder
- cmd := listCmd{
- devFinderCmd: devFinderCmd{output: &buf},
- fullInfo: true,
- }
- cmd.outputNormal(devs)
+ {
+ var buf strings.Builder
+ cmd := devFinderCmd{output: &buf}
+ cmd.outputNormal(devs, true)
- got := buf.String()
- want := `123.12.234.23 hello.world
+ got := buf.String()
+ want := `123.12.234.23 hello.world
11.22.33.44 fuchsia.rocks
`
- if d := cmp.Diff(want, got); d != "" {
- t.Errorf("outputNormal mismatch: (-want +got):\n%s", d)
+ if d := cmp.Diff(want, got); d != "" {
+ t.Errorf("outputNormal(includeDomain) mismatch: (-want +got):\n%s", d)
+ }
}
+
}
-func TestListOutputJSON(t *testing.T) {
+func TestOutputJSON(t *testing.T) {
devs := []*fuchsiaDevice{
{
- addr: net.ParseIP("123.12.234.23"),
- },
- {
- addr: net.ParseIP("11.22.33.44"),
- },
- }
- var buf bytes.Buffer
- cmd := listCmd{
- devFinderCmd: devFinderCmd{
- json: true,
- output: &buf,
- },
- }
- cmd.outputJSON(devs)
-
- var got jsonOutput
- if err := json.Unmarshal(buf.Bytes(), &got); err != nil {
- t.Fatalf("json.Unmarshal: %v", err)
- }
-
- want := jsonOutput{
- Devices: []jsonDevice{
- {Addr: "123.12.234.23"},
- {Addr: "11.22.33.44"},
- },
- }
-
- if d := cmp.Diff(want, got); d != "" {
- t.Errorf("outputNormal mismatch: (-want +got):\n%s", d)
- }
-}
-
-func TestListOutputJSON_fullInfo(t *testing.T) {
- devs := []*fuchsiaDevice{
- {
- addr: net.ParseIP("123.12.234.23"),
+ addr: net.ParseIP("123.12.234.23").To4(),
domain: "hello.world",
},
{
- addr: net.ParseIP("11.22.33.44"),
+ addr: net.ParseIP("11.22.33.44").To4(),
domain: "fuchsia.rocks",
},
}
- var buf bytes.Buffer
- cmd := listCmd{
- devFinderCmd: devFinderCmd{
+
+ {
+ var buf bytes.Buffer
+ cmd := devFinderCmd{
json: true,
output: &buf,
- },
- fullInfo: true,
- }
- cmd.outputJSON(devs)
+ }
- var got jsonOutput
- if err := json.Unmarshal(buf.Bytes(), &got); err != nil {
- t.Fatalf("json.Unmarshal: %v", err)
- }
+ cmd.outputJSON(devs, false)
- want := jsonOutput{
- Devices: []jsonDevice{
- {
- Addr: "123.12.234.23",
- Domain: "hello.world",
+ var got jsonOutput
+ if err := json.Unmarshal(buf.Bytes(), &got); err != nil {
+ t.Fatalf("json.Unmarshal: %v", err)
+ }
+ want := jsonOutput{
+ Devices: []jsonDevice{
+ {Addr: "123.12.234.23"},
+ {Addr: "11.22.33.44"},
},
- {
- Addr: "11.22.33.44",
- Domain: "fuchsia.rocks",
- },
- },
+ }
+ if d := cmp.Diff(want, got); d != "" {
+ t.Errorf("outputNormal mismatch: (-want +got):\n%s", d)
+ }
}
- if d := cmp.Diff(want, got); d != "" {
- t.Errorf("outputNormal mismatch: (-want +got):\n%s", d)
+ {
+ var buf bytes.Buffer
+ cmd := devFinderCmd{
+ json: true,
+ output: &buf,
+ }
+
+ cmd.outputJSON(devs, true)
+
+ var got jsonOutput
+ if err := json.Unmarshal(buf.Bytes(), &got); err != nil {
+ t.Fatalf("json.Unmarshal: %v", err)
+ }
+
+ want := jsonOutput{
+ Devices: []jsonDevice{
+ {
+ Addr: "123.12.234.23",
+ Domain: "hello.world",
+ },
+ {
+ Addr: "11.22.33.44",
+ Domain: "fuchsia.rocks",
+ },
+ },
+ }
+ if d := cmp.Diff(want, got); d != "" {
+ t.Errorf("outputNormal(includeDomain) mismatch: (-want +got):\n%s", d)
+ }
}
}
diff --git a/cmd/dev_finder/list.go b/cmd/dev_finder/list.go
index c11ee01..248e8cd 100644
--- a/cmd/dev_finder/list.go
+++ b/cmd/dev_finder/list.go
@@ -6,7 +6,6 @@
import (
"context"
- "encoding/json"
"flag"
"fmt"
"log"
@@ -77,7 +76,7 @@
}
}
-func (cmd *listCmd) findDevices(ctx context.Context) ([]*fuchsiaDevice, error) {
+func (cmd *listCmd) listDevices(ctx context.Context) ([]*fuchsiaDevice, error) {
listPacket := mdns.Packet{
Header: mdns.Header{QDCount: 1},
Questions: []mdns.Question{
@@ -106,42 +105,15 @@
}
func (cmd *listCmd) execute(ctx context.Context) error {
- filteredDevices, err := cmd.findDevices(ctx)
+ filteredDevices, err := cmd.listDevices(ctx)
if err != nil {
return err
}
if cmd.json {
- return cmd.outputJSON(filteredDevices)
+ return cmd.outputJSON(filteredDevices, cmd.fullInfo)
}
- return cmd.outputNormal(filteredDevices)
-}
-
-func (cmd *listCmd) outputNormal(filteredDevices []*fuchsiaDevice) error {
- for _, device := range filteredDevices {
- if cmd.fullInfo {
- fmt.Fprintf(cmd.Output(), "%v %v\n", device.addr, device.domain)
- } else {
- fmt.Fprintf(cmd.Output(), "%v\n", device.addr)
- }
- }
- return nil
-}
-
-func (cmd *listCmd) outputJSON(filteredDevices []*fuchsiaDevice) error {
- jsonOut := jsonOutput{Devices: make([]jsonDevice, 0, len(filteredDevices))}
-
- for _, device := range filteredDevices {
- dev := jsonDevice{Addr: device.addr.String()}
- if cmd.fullInfo {
- dev.Domain = device.domain
- }
- jsonOut.Devices = append(jsonOut.Devices, dev)
- }
-
- e := json.NewEncoder(cmd.Output())
- e.SetIndent("", " ")
- return e.Encode(jsonOut)
+ return cmd.outputNormal(filteredDevices, cmd.fullInfo)
}
func (cmd *listCmd) Execute(ctx context.Context, _ *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
diff --git a/cmd/dev_finder/resolve.go b/cmd/dev_finder/resolve.go
index 7b82550..c5f8796 100644
--- a/cmd/dev_finder/resolve.go
+++ b/cmd/dev_finder/resolve.go
@@ -5,13 +5,11 @@
import (
"context"
- "encoding/json"
"errors"
"flag"
"fmt"
"log"
"net"
- "os"
"github.com/google/subcommands"
@@ -60,9 +58,9 @@
}
}
-func (cmd *resolveCmd) execute(ctx context.Context, domains ...string) error {
+func (cmd *resolveCmd) resolveDevices(ctx context.Context, domains ...string) ([]*fuchsiaDevice, error) {
if len(domains) == 0 {
- return errors.New("no domains supplied")
+ return nil, errors.New("no domains supplied")
}
var outDevices []*fuchsiaDevice
@@ -70,7 +68,7 @@
mDNSDomain := fmt.Sprintf("%s.local", domain)
devices, err := cmd.sendMDNSPacket(ctx, mdns.QuestionPacket(mDNSDomain))
if err != nil {
- return fmt.Errorf("sending/receiving mdns packets during resolve of domain '%s': %v", domain, err)
+ return nil, fmt.Errorf("sending/receiving mdns packets during resolve of domain '%s': %v", domain, err)
}
filteredDevices := make([]*fuchsiaDevice, 0)
for _, device := range devices {
@@ -79,36 +77,26 @@
}
}
if len(filteredDevices) == 0 {
- return fmt.Errorf("no devices with domain %v", domain)
+ return nil, fmt.Errorf("no devices with domain %v", domain)
}
for _, device := range filteredDevices {
outDevices = append(outDevices, device)
}
}
+ return outDevices, nil
+}
+
+func (cmd *resolveCmd) execute(ctx context.Context, domains ...string) error {
+ outDevices, err := cmd.resolveDevices(ctx, domains...)
+ if err != nil {
+ return err
+ }
if cmd.json {
- return cmd.outputJSON(outDevices)
+ return cmd.outputJSON(outDevices, false /* includeDomain */)
}
- return cmd.outputNormal(outDevices)
-}
-
-func (cmd *resolveCmd) outputNormal(devices []*fuchsiaDevice) error {
- for _, device := range devices {
- fmt.Println(device.addr)
- }
- return nil
-}
-
-func (cmd *resolveCmd) outputJSON(devices []*fuchsiaDevice) error {
- jsonOut := jsonOutput{Devices: make([]jsonDevice, 0, len(devices))}
- for _, device := range devices {
- jsonOut.Devices = append(jsonOut.Devices, jsonDevice{Addr: device.addr.String()})
- }
-
- e := json.NewEncoder(os.Stdout)
- e.SetIndent("", " ")
- return e.Encode(jsonOut)
+ return cmd.outputNormal(outDevices, false /* includeDomain */)
}
func (cmd *resolveCmd) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {