Skip to content

Commit

Permalink
Add net testing work
Browse files Browse the repository at this point in the history
  • Loading branch information
Will Gough committed Jul 10, 2018
0 parents commit f7c8c99
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 0 deletions.
99 changes: 99 additions & 0 deletions 2018/July/net-testing/net.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package net

import (
"bufio"
"errors"
"fmt"
"net"
"strings"
)

// Server defines the minimum contract our
// TCP and UDP server implementations must satisfy.
type Server interface {
Run() error
Close() error
}

// NewServer creates a new Server using given protocol
// and addr.
func NewServer(protocol, addr string) (Server, error) {
switch strings.ToLower(protocol) {
case "tcp":
return &TCPServer{
addr: addr,
}, nil
case "udp":
}
return nil, errors.New("Invalid protocol given")
}

// TCPServer holds the structure of our TCP
// implementation.
type TCPServer struct {
addr string
server net.Listener
}

// Run starts the TCP Server.
func (t *TCPServer) Run() (err error) {
t.server, err = net.Listen("tcp", t.addr)
if err != nil {
return err
}
defer t.Close()

for {
conn, err := t.server.Accept()
if err != nil {
err = errors.New("could not accept connection")
break
}
if conn == nil {
err = errors.New("could not create connection")
break
}
return t.handleConnections()
}
return
}

// Close shuts down the TCP Server
func (t *TCPServer) Close() (err error) {
return t.server.Close()
}

// handleConnections is used to accept connections on
// the TCPServer and handle each of them in separate
// goroutines.
func (t *TCPServer) handleConnections() (err error) {
for {
conn, err := t.server.Accept()
if err != nil || conn == nil {
err = errors.New("could not accept connection")
break
}

go t.handleConnection(conn)
}
return
}

// handleConnections deals with the business logic of
// each connection and their requests.
func (t *TCPServer) handleConnection(conn net.Conn) {
defer conn.Close()

rw := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
for {
req, err := rw.ReadString('\n')
if err != nil {
rw.WriteString("failed to read input")
rw.Flush()
return
}

rw.WriteString(fmt.Sprintf("Request received: %s", req))
rw.Flush()
}
}
68 changes: 68 additions & 0 deletions 2018/July/net-testing/net_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package net

import (
"bytes"
"log"
"net"
"testing"
)

var srv Server

func init() {
// Start the new server
srv, err := NewServer("tcp", ":1123")
if err != nil {
log.Println("error starting TCP server")
return
}

// Run the server in goroutine to stop blocking
go func() {
srv.Run()
}()
}

func TestNETServer_Running(t *testing.T) {
// Simply check that the server is up and can
// accept connections.
conn, err := net.Dial("tcp", ":1123")
if err != nil {
t.Error("could not connect to server: ", err)
}
defer conn.Close()
}

func TestNETServer_Request(t *testing.T) {
tt := []struct {
test string
payload []byte
want []byte
}{
{"Sending a simple request returns result", []byte("hello world\n"), []byte("Request received: hello world")},
{"Sending another simple request works", []byte("goodbye world\n"), []byte("Request received: goodbye world")},
}

for _, tc := range tt {
t.Run(tc.test, func(t *testing.T) {
conn, err := net.Dial("tcp", ":1123")
if err != nil {
t.Error("could not connect to TCP server: ", err)
}
defer conn.Close()

if _, err := conn.Write(tc.payload); err != nil {
t.Error("could not write payload to TCP server:", err)
}

out := make([]byte, 1024)
if _, err := conn.Read(out); err == nil {
if bytes.Compare(out, tc.want) == 0 {
t.Error("response did match expected output")
}
} else {
t.Error("could not read from connection")
}
})
}
}
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
### DevTheWeb Post Source Code

This repository holds all the source code for the posts and examples given on my personal site: [devtheweb.io](https://devtheweb.io).

To find the code you want, simply find the date of the post you're looking at and navigate through the subfolders: `year/month/subject`.

0 comments on commit f7c8c99

Please sign in to comment.