Skip to content

Commit 1b90560

Browse files
authored
Merge pull request #120 from HyperloopUPV-H8/backend/unit-tests
[backend] [PR 1] Unit tests / Transport Short
2 parents 07c83d0 + 39e38d6 commit 1b90560

5 files changed

Lines changed: 288 additions & 2 deletions

File tree

backend/pkg/transport/network/tcp/config.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ const (
4747
// It follows this formula: delay = (min * (exp ^ n); delay < max ? delay : max
4848
func NewExponentialBackoff(min time.Duration, exp float64, max time.Duration) backoffFunction {
4949
return func(n int) time.Duration {
50-
curr := min
51-
curr = time.Duration(math.Trunc(math.Pow(float64(curr), exp)))
50+
curr := time.Duration(float64(min) * math.Trunc(math.Pow(exp, float64(n))))
5251
if curr >= max {
5352
return max
5453
}
@@ -62,3 +61,12 @@ type ServerConfig struct {
6261

6362
Context context.Context
6463
}
64+
65+
func NewServerConfig() ServerConfig {
66+
return ServerConfig{
67+
ListenConfig: net.ListenConfig{
68+
KeepAlive: time.Second,
69+
},
70+
Context: context.TODO(),
71+
}
72+
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package tcp_test
2+
3+
import (
4+
"github.com/HyperloopUPV-H8/h9-backend/pkg/transport/network/tcp"
5+
"github.com/rs/zerolog"
6+
"net"
7+
"os"
8+
"testing"
9+
"time"
10+
)
11+
12+
type Socket struct {
13+
SrcIP string
14+
SrcPort uint16
15+
DstIP string
16+
DstPort uint16
17+
}
18+
19+
// Payload defines a piece of information coming from the network with its metadata
20+
type Payload struct {
21+
Timestamp time.Time
22+
Socket Socket
23+
Data []byte
24+
}
25+
26+
type Addr struct {
27+
Net string
28+
Addr string
29+
}
30+
31+
func (a Addr) Network() string {
32+
return a.Net
33+
}
34+
35+
func (a Addr) String() string {
36+
return a.Addr
37+
}
38+
39+
func TestTCP(t *testing.T) {
40+
logger := zerolog.New(os.Stdout)
41+
42+
// Server setup
43+
serverAddrSol, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:8080")
44+
serverAddr := serverAddrSol.String()
45+
46+
server := tcp.NewServer(serverAddr, tcp.NewServerConfig(), logger)
47+
server.AddToWhitelist("127.0.0.1")
48+
49+
server.OnConnection(func(conn net.Conn) error {
50+
defer conn.Close()
51+
52+
for {
53+
// Read and echo back the Payload
54+
buffer := make([]byte, len([]byte("hello")))
55+
_, err := conn.Read(buffer)
56+
if err != nil {
57+
println("Failed to read from client: %v", err)
58+
}
59+
_, err = conn.Write(buffer)
60+
if err != nil {
61+
println("Failed to write to client: %v", err)
62+
}
63+
}
64+
65+
})
66+
67+
go func() {
68+
defer server.Close()
69+
err := server.Listen()
70+
if err != nil {
71+
t.Fatalf("Server failed to listen: %v", err)
72+
}
73+
}()
74+
75+
// Client setup
76+
addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:3000")
77+
client := tcp.NewClient(serverAddr, tcp.NewClientConfig(net.Addr(addr)), logger)
78+
79+
time.Sleep(10 * time.Millisecond)
80+
81+
conn, err := client.Dial()
82+
if err != nil {
83+
t.Fatalf("Client failed to dial: %v", err)
84+
}
85+
defer conn.Close()
86+
87+
// Create and send Payload
88+
originalPayload := Payload{
89+
Timestamp: time.Now(),
90+
Socket: Socket{
91+
SrcIP: "127.0.0.1",
92+
SrcPort: 3000,
93+
DstIP: "127.0.0.1",
94+
DstPort: 8080,
95+
},
96+
Data: []byte("hello"),
97+
}
98+
_, err = conn.Write(originalPayload.Data)
99+
if err != nil {
100+
t.Fatalf("Failed to write Payload to server: %v", err)
101+
}
102+
103+
// Read file
104+
buffer := make([]byte, len([]byte("hello")))
105+
_, err = conn.Read(buffer)
106+
if err != nil {
107+
t.Fatalf("Failed to read from server: %v", err)
108+
}
109+
110+
// Verify Payload content when echoed back
111+
if string(buffer) != string(originalPayload.Data) {
112+
t.Fatalf("Expected message '%s', got '%s'", string(originalPayload.Data), string(buffer))
113+
}
114+
115+
server.Close()
116+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
hello
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package tftp_test
2+
3+
import (
4+
"github.com/HyperloopUPV-H8/h9-backend/pkg/transport/network/tftp"
5+
tftpv3 "github.com/pin/tftp/v3"
6+
"io"
7+
"os"
8+
"testing"
9+
"time"
10+
)
11+
12+
func TestTFTP(t *testing.T) {
13+
serverAddr := "127.0.0.1:3000"
14+
fileName := "testfile"
15+
fileContent := "hello"
16+
17+
os.Create(fileName)
18+
os.WriteFile(fileName, []byte(fileContent), 0644)
19+
20+
// Server setup
21+
readerFunc := func(filename string, rf io.ReaderFrom) error {
22+
file, err := os.OpenFile(fileName, os.O_RDONLY, 0644)
23+
if err != nil {
24+
return err
25+
}
26+
defer file.Close()
27+
_, err = rf.ReadFrom(file)
28+
return err
29+
}
30+
31+
writerFunc := func(filename string, wt io.WriterTo) error {
32+
file, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY, 0644)
33+
if err != nil {
34+
return err
35+
}
36+
defer file.Close()
37+
_, err = wt.WriteTo(file)
38+
return err
39+
}
40+
41+
server := tftpv3.NewServer(readerFunc, writerFunc)
42+
43+
go func() {
44+
err := server.ListenAndServe(serverAddr)
45+
if err != nil {
46+
t.Fatalf("Server failed to listen: %v", err)
47+
}
48+
}()
49+
50+
println("Server listening on", serverAddr)
51+
52+
time.Sleep(10 * time.Millisecond)
53+
54+
// Initialize TFTP client
55+
client, err := tftp.NewClient(serverAddr)
56+
if err != nil {
57+
t.Fatalf("Failed to create TFTP client: %v", err)
58+
}
59+
println("Client connected to", serverAddr)
60+
61+
// Open the file to upload
62+
file, err := os.OpenFile(fileName, os.O_RDONLY, 0644)
63+
64+
// Write to the server
65+
n, err := client.WriteFile(fileName, tftp.BinaryMode, io.Reader(file))
66+
if err != nil {
67+
t.Fatalf("Failed to write to server: %v", err)
68+
}
69+
println("Uploaded", n, "bytes")
70+
71+
file.Close()
72+
73+
// Read from the server
74+
file, _ = os.OpenFile(fileName, os.O_WRONLY, 0644)
75+
n, err = client.ReadFile(fileName, tftp.BinaryMode, io.Writer(file))
76+
if err != nil {
77+
t.Fatalf("Failed to read from server: %v", err)
78+
}
79+
println("Downloaded", n, "bytes")
80+
81+
file.Close()
82+
83+
// Validate the downloaded data matches what was uploaded
84+
buffer := make([]byte, len(fileContent))
85+
file, _ = os.OpenFile(fileName, os.O_RDONLY, 0644)
86+
io.ReadFull(file, buffer)
87+
if string(buffer) != fileContent {
88+
t.Errorf("Downloaded content mismatch. Expected: %s, Got: %s", fileContent, string(buffer))
89+
}
90+
println("Downloaded content matches the uploaded content")
91+
92+
os.Remove(fileName)
93+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package transport_test
2+
3+
import (
4+
"context"
5+
"net"
6+
"os"
7+
"sync"
8+
"testing"
9+
"time"
10+
11+
transport_module "github.com/HyperloopUPV-H8/h9-backend/pkg/transport"
12+
"github.com/HyperloopUPV-H8/h9-backend/pkg/transport/network/tcp"
13+
"github.com/rs/zerolog"
14+
)
15+
16+
func TestTransport(t *testing.T) {
17+
logger := zerolog.New(os.Stdout)
18+
transport := transport_module.NewTransport(logger)
19+
20+
// Create a context that cancels after a timeout
21+
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Millisecond)
22+
defer cancel()
23+
24+
var wg sync.WaitGroup
25+
26+
wg.Add(1)
27+
go func() {
28+
defer wg.Done()
29+
err := transport.HandleServer(tcp.NewServerConfig(), "127.0.0.1:8080")
30+
if err != nil {
31+
t.Errorf("Error creating server at 127.0.0.1:8080: %s", err)
32+
}
33+
}()
34+
35+
time.Sleep(10 * time.Millisecond)
36+
37+
// Simulate client interaction
38+
addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:3000")
39+
wg.Add(1)
40+
go func() {
41+
defer wg.Done()
42+
err := transport.HandleClient(tcp.NewClientConfig(addr), "127.0.0.1:8080")
43+
if err != nil {
44+
t.Errorf("Error creating client at 127.0.0.1:3000: %s", err)
45+
}
46+
}()
47+
48+
// Create client with wrong address
49+
addr, _ = net.ResolveTCPAddr("tcp", "127.0.0.1:3030")
50+
wg.Add(1)
51+
go func() {
52+
defer wg.Done()
53+
err := transport.HandleClient(tcp.NewClientConfig(addr), "127.0.0.1:8000")
54+
if err == nil {
55+
t.Errorf("Expected error creating client at wrong address, got nil")
56+
}
57+
}()
58+
59+
// Wait for context cancellation or error
60+
go func() {
61+
wg.Wait()
62+
}()
63+
64+
<-ctx.Done() // Wait for timeout or manual cancel
65+
if ctx.Err() == context.DeadlineExceeded {
66+
t.Logf("Test completed by timeout")
67+
}
68+
}

0 commit comments

Comments
 (0)