Skip to content

Commit

Permalink
Add tests (#8)
Browse files Browse the repository at this point in the history
* Update package, add td2 client tests

* Run tests in release workflow

* Add checkout

* Add mocked frontend dist directory

* Add mocked frontend dist directory

* More reliable tests

* Better client tests

* CAdd test for connection failed

* Use parser function from station package
  • Loading branch information
KacperMalachowski authored Mar 27, 2024
1 parent 84f82a9 commit 9d1cd07
Show file tree
Hide file tree
Showing 8 changed files with 284 additions and 8 deletions.
19 changes: 18 additions & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,25 @@ env:
NODE_OPTIONS: "--max-old-space-size=4096"

jobs:
test-go:
name: Test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Golang
uses: actions/setup-go@v4
with:
check-latest: true
go-version: '1.21'
- run: mkdir -p frontend/dist && touch frontend/dist/test.txt
- run: go test ./...

build:
name: Build
needs: test-go
strategy:
matrix:
os: [windows]
Expand Down Expand Up @@ -44,7 +61,7 @@ jobs:
run: brew install mitchellh/gon/gon

- name: Build App
run: wails build --platform ${{ matrix.os}}/${{ matrix.arch }} -webview2 download -o marshaller-${{ matrix.os }}-${{ matrix.arch }}
run: wails build --platform ${{ matrix.os}}/${{ matrix.arch }} -webview2 embed -o marshaller-${{ matrix.os }}-${{ matrix.arch }}

- name: Add macOS permissions
if: runner.os == 'macOS'
Expand Down
9 changes: 4 additions & 5 deletions app.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package main

import (
"changeme/pkg/station"
"changeme/pkg/td2"
"context"
"crypto/sha256"
"fmt"
"os"

"github.com/kacpermalachowski/marshal-controller/pkg/station"
"github.com/kacpermalachowski/marshal-controller/pkg/td2"

"github.com/wailsapp/wails/v2/pkg/runtime"
"gopkg.in/yaml.v3"
)

type App struct {
Expand Down Expand Up @@ -50,8 +50,7 @@ func (a *App) LoadStationFile() station.Definition {
return a.station
}

var station station.Definition
err = yaml.Unmarshal(data, &station)
station, err := station.ParseStationDefinition(data)
if err != nil {
runtime.LogError(a.ctx, fmt.Sprint(err))
return a.station
Expand Down
3 changes: 2 additions & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package main

import (
"bufio"
"changeme/pkg/td2"
"context"
"fmt"
"log"
"os"

"github.com/kacpermalachowski/marshal-controller/pkg/td2"
)

func main() {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module changeme
module github.com/kacpermalachowski/marshal-controller

go 1.21

Expand Down
52 changes: 52 additions & 0 deletions internal/testserver/testserver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package testserver

import (
"fmt"
"net"
)

type TestTCPServer struct {
ReceivedDataChan chan string
}

func New() *TestTCPServer {
return &TestTCPServer{
ReceivedDataChan: make(chan string),
}
}

func (s *TestTCPServer) Start() (string, error) {
l, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
return "", fmt.Errorf("failed to start test server: %s", err)
}

go func() {
defer l.Close()

for {
conn, err := l.Accept()
if err != nil {
return
}

go func(c net.Conn) {
defer c.Close()

buf := make([]byte, 1024)
n, err := c.Read(buf)
if err != nil {
return
}

s.ReceivedDataChan <- string(buf[:n])
}(conn)
}
}()

return l.Addr().String(), nil
}

func (s *TestTCPServer) Stop() {
close(s.ReceivedDataChan)
}
20 changes: 20 additions & 0 deletions pkg/station/station.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package station

import (
"fmt"

"gopkg.in/yaml.v3"
)

type Definition struct {
Hills []Hill `json:"hills" yaml:"hills"`
}
Expand All @@ -8,3 +14,17 @@ type Hill struct {
Signal string `json:"signal" yaml:"signal"`
Repeaters []string `json:"repeaters" yaml:"repeaters"`
}

func ParseStationDefinition(data []byte) (Definition, error) {
var station Definition
err := yaml.Unmarshal(data, &station)
if err != nil {
return Definition{}, err
}

if len(station.Hills) == 0 {
return Definition{}, fmt.Errorf("the program is unusable without hills defined")
}

return station, err
}
94 changes: 94 additions & 0 deletions pkg/station/station_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package station_test

import (
"reflect"
"testing"

"github.com/kacpermalachowski/marshal-controller/pkg/station"
)

func TestParseStationDefinition(t *testing.T) {
tc := []struct {
Name string
Data string
Expected station.Definition
ExpectErr bool
}{
{
Name: "No hills",
Data: `hills:`,
ExpectErr: true,
},
{
Name: "Single hill and signal",
Data: `hills:
- signal: Tr1`,
Expected: station.Definition{
Hills: []station.Hill{
{
Signal: "Tr1",
},
},
},
},
{
Name: "Single hill with repeaters",
Data: `hills:
- signal: Tr1
repeaters:
- Tr2`,
Expected: station.Definition{
Hills: []station.Hill{
{
Signal: "Tr1",
Repeaters: []string{
"Tr2",
},
},
},
},
},
{
Name: "Multiple hill with repeaters",
Data: `hills:
- signal: Tr1
repeaters:
- Tr2
- signal: Tr3
repeaters:
- Tr4`,
Expected: station.Definition{
Hills: []station.Hill{
{
Signal: "Tr1",
Repeaters: []string{
"Tr2",
},
},
{
Signal: "Tr3",
Repeaters: []string{
"Tr4",
},
},
},
},
},
}

for _, c := range tc {
t.Run(c.Name, func(t *testing.T) {
def, err := station.ParseStationDefinition([]byte(c.Data))
if err != nil && !c.ExpectErr {
t.Errorf("Unexpected error occured: %s", err)
}
if c.ExpectErr && err == nil {
t.Error("Expected error, but no one occured")
}

if !reflect.DeepEqual(c.Expected, def) {
t.Errorf("Expected %v, but got %v", c.Expected, def)
}
})
}
}
93 changes: 93 additions & 0 deletions pkg/td2/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package td2_test

import (
"context"
"fmt"
"testing"

"github.com/kacpermalachowski/marshal-controller/internal/testserver"
"github.com/kacpermalachowski/marshal-controller/pkg/td2"
)

func TestNewClient(t *testing.T) {
ctx := context.Background()
stationHash := "exampleHash"
client := td2.New(ctx, stationHash)

if client.IsConnected {
t.Error("Expected IsConnected to be false, but got true")
}

if len(client.ReadChan) != 0 {
t.Error("Expected ReadChan to be empty, but it is not")
}
}

func TestConnectDisconnect(t *testing.T) {
ctx := context.Background()
stationHash := "exampleHash"
client := td2.New(ctx, stationHash)

server := testserver.New()
addr, err := server.Start()
if err != nil {
t.Fatalf("Failed to setup test server: %s", err)
}

// Test Connect
err = client.Connect(addr)
if err != nil {
t.Errorf("Expected no error on Connect, but got: %v", err)
}

if !client.IsConnected {
t.Error("Expected IsConnected to be true after Connect, but got false")
}

// Test Disconnect
client.Disconnect()
if client.IsConnected {
t.Error("Expected IsConnected to be false after Disconnect, but got true")
}
}

func TestConnectionFailed(t *testing.T) {
ctx := context.Background()
stationHash := "exampleHash"
client := td2.New(ctx, stationHash)

err := client.Connect("127.0.0.1:0")
if err == nil {
t.Error("Expected error on Connect, but got nothing")
}
}

func TestWrite(t *testing.T) {
ctx := context.Background()
stationHash := "exampleHash"
client := td2.New(ctx, stationHash)
testData := "Hello, World!"
expectedData := fmt.Sprintf("%s\r\n", testData)

server := testserver.New()
addr, err := server.Start()
if err != nil {
t.Fatalf("Failed to setup test server: %s", err)
}

err = client.Connect(addr)
if err != nil {
t.Errorf("Failed to connect: %s", err)
}
defer client.Disconnect()

err = client.Write(testData)
if err != nil {
t.Errorf("Expected no error on Write operation, but got: %s", err)
}

receivedData := <-server.ReceivedDataChan
if receivedData != expectedData {
t.Errorf("Expected written data to be %q, but got %q", expectedData, receivedData)
}
}

0 comments on commit 9d1cd07

Please sign in to comment.