Skip to content

Commit

Permalink
feat: add common parasble types
Browse files Browse the repository at this point in the history
  • Loading branch information
ajatprabha committed Feb 15, 2024
1 parent 72aee65 commit 1f93e2c
Show file tree
Hide file tree
Showing 4 changed files with 250 additions and 0 deletions.
32 changes: 32 additions & 0 deletions xload/type/endpoint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package xloadtype

import (
"fmt"
"net"
"strconv"
)

type Endpoint struct {
Host string
Port int
}

func (e *Endpoint) String() string { return fmt.Sprintf("%s:%d", e.Host, e.Port) }

func (e *Endpoint) Decode(v string) error {
host, port, err := net.SplitHostPort(v)
if err != nil {
return err
}

e.Host = host

p, err := strconv.ParseInt(port, 10, 32)
if err != nil {
return err
}

e.Port = int(p)

return nil
}
75 changes: 75 additions & 0 deletions xload/type/endpoint_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package xloadtype

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestEndpoint_Decode(t *testing.T) {
tests := []struct {
name string
in string
want *Endpoint
wantErr assert.ErrorAssertionFunc
}{
{
name: "valid",
in: "localhost:8080",
want: &Endpoint{
Host: "localhost",
Port: 8080,
},
wantErr: assert.NoError,
},
{
name: "invalid",
in: "localhost",
want: &Endpoint{},
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
return assert.EqualError(t, err, "address localhost: missing port in address")
},
},
{
name: "invalid port",
in: "localhost:port",
want: &Endpoint{Host: "localhost"},
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
return assert.EqualError(t, err, `strconv.ParseInt: parsing "port": invalid syntax`)
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
e := new(Endpoint)
tt.wantErr(t, e.Decode(tt.in))
assert.Equal(t, tt.want, e)
})
}
}

func TestEndpoint_String(t *testing.T) {
tests := []struct {
name string
in *Endpoint
want string
}{
{
name: "valid",
in: &Endpoint{Host: "localhost", Port: 8080},
want: "localhost:8080",
},
{
name: "empty",
in: &Endpoint{},
want: ":0",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.want, tt.in.String())
})
}
}
44 changes: 44 additions & 0 deletions xload/type/listener.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package xloadtype

import (
"fmt"
"net"
"strconv"
)

type Listener struct {
IP net.IP
Port int
}

func (l *Listener) String() string {
if l.IP == nil {
return fmt.Sprintf(":%d", l.Port)
}

return net.JoinHostPort(l.IP.String(), strconv.Itoa(l.Port))
}

func (l *Listener) Decode(v string) error {
host, port, err := net.SplitHostPort(v)
if err != nil {
return err
}

if host != "" {
l.IP = net.ParseIP(host)

if l.IP == nil {
return net.InvalidAddrError("invalid IP address")
}
}

p, err := strconv.ParseInt(port, 10, 32)
if err != nil {
return err
}

l.Port = int(p)

return err
}
99 changes: 99 additions & 0 deletions xload/type/listener_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package xloadtype

import (
"github.com/stretchr/testify/assert"
"net"
"testing"
)

func TestListener_Decode(t *testing.T) {
tests := []struct {
name string
in string
want *Listener
wantErr assert.ErrorAssertionFunc
}{
{
name: "valid ipv4",
in: "127.0.0.1:8080",
want: &Listener{
IP: net.IPv4(127, 0, 0, 1),
Port: 8080,
},
wantErr: assert.NoError,
},
{
name: "valid ipv6",
in: "[::1]:8080",
want: &Listener{
IP: net.IPv6loopback,
Port: 8080,
},
wantErr: assert.NoError,
},
{
name: "missing port",
in: "localhost",
want: &Listener{},
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
return assert.EqualError(t, err, "address localhost: missing port in address")
},
},
{
name: "invalid port",
in: "127.0.0.1:port",
want: &Listener{IP: net.IPv4(127, 0, 0, 1)},
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
return assert.EqualError(t, err, `strconv.ParseInt: parsing "port": invalid syntax`)
},
},
{
name: "invalid ip",
in: "localhost:8080",
want: &Listener{},
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
return assert.EqualError(t, err, "invalid IP address")
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := new(Listener)
tt.wantErr(t, l.Decode(tt.in))
assert.Equal(t, tt.want, l)
})
}
}

func TestListener_String(t *testing.T) {
tests := []struct {
name string
in *Listener
want string
}{
{
name: "valid ipv4",
in: &Listener{IP: net.IPv4(127, 0, 0, 1), Port: 8080},
want: "127.0.0.1:8080",
},
{
name: "valid ipv6",
in: &Listener{IP: net.IPv6loopback, Port: 8080},
want: "[::1]:8080",
},
{
name: "empty ip",
in: &Listener{
Port: 8080,
},
want: ":8080",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.want, tt.in.String())
})
}
}

0 comments on commit 1f93e2c

Please sign in to comment.