Skip to content

Commit

Permalink
Fixed unmarshalling tasklist with invalid/missing JSON
Browse files Browse the repository at this point in the history
  • Loading branch information
twystd committed Jun 20, 2024
1 parent b2a3c03 commit 3f23371
Show file tree
Hide file tree
Showing 5 changed files with 333 additions and 5 deletions.
4 changes: 4 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
- [x] CHANGELOG
- [x] README

- [x] _405419896 error loading tasklist (unexpected end of JSON input)_
- [ ] Check `dump` udp/tcp packet labellingmay be mislabelling udp/tcp packets


## TODO

- [ ] Verify fields in listen events/status replies against SDK
Expand Down
2 changes: 1 addition & 1 deletion entities/tasklist.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
)

type TaskList struct {
Tasks []types.Task `json:"tasks"`
Tasks []types.Task `json:"tasks,omitempty"`
added []types.Task
scheduled map[int]scheduled
last string
Expand Down
81 changes: 81 additions & 0 deletions entities/tasklist_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package entities

import (
"encoding/json"
"testing"
"time"

lib "github.com/uhppoted/uhppote-core/types"
)

func TestTaskListToJSON(t *testing.T) {
tasklist := TaskList{
Tasks: []lib.Task{
lib.Task{
Task: lib.DoorControlled,
Door: 2,
From: lib.MustParseDate("2024-01-01"),
To: lib.MustParseDate("2024-12-31"),
Weekdays: lib.Weekdays{
time.Monday: true,
time.Wednesday: false,
time.Friday: true,
},
Start: lib.NewHHmm(12, 34),
Cards: 17,
},
},
added: []lib.Task{
lib.Task{
Task: lib.EnableTimeProfile,
Door: 3,
From: lib.MustParseDate("2023-01-01"),
To: lib.MustParseDate("2025-12-31"),
Weekdays: lib.Weekdays{
time.Tuesday: true,
},
Start: lib.NewHHmm(21, 22),
Cards: 13,
},
},
scheduled: map[int]scheduled{},
last: "2024-06-20",
}

expected := `{"tasks":[{"task":"CONTROL DOOR","door":2,"start-date":"2024-01-01","end-date":"2024-12-31","weekdays":"Monday,Friday","start":"12:34","cards":17}]}`

if bytes, err := json.Marshal(tasklist); err != nil {

Check failure on line 47 in entities/tasklist_test.go

View workflow job for this annotation

GitHub Actions / Build

call of json.Marshal copies lock value: github.com/uhppoted/uhppote-simulator/entities.TaskList contains sync.Mutex
t.Fatalf("Error marshalling task list (%v)", err)
} else if string(bytes) != expected {
t.Errorf("TaskList marshalled incorrectly:\n expected:%v\n got: %v", expected, string(bytes))
}
}

func TestEmptyTaskListToJSON(t *testing.T) {
tasklist := TaskList{
Tasks: []lib.Task{},
added: []lib.Task{
lib.Task{
Task: lib.EnableTimeProfile,
Door: 3,
From: lib.MustParseDate("2023-01-01"),
To: lib.MustParseDate("2025-12-31"),
Weekdays: lib.Weekdays{
time.Tuesday: true,
},
Start: lib.NewHHmm(21, 22),
Cards: 13,
},
},
scheduled: map[int]scheduled{},
last: "2024-06-20",
}

expected := `{}`

if bytes, err := json.Marshal(tasklist); err != nil {

Check failure on line 76 in entities/tasklist_test.go

View workflow job for this annotation

GitHub Actions / Build

call of json.Marshal copies lock value: github.com/uhppoted/uhppote-simulator/entities.TaskList contains sync.Mutex
t.Fatalf("Error marshalling task list (%v)", err)
} else if string(bytes) != expected {
t.Errorf("TaskList marshalled incorrectly:\n expected:%v\n got: %v", expected, string(bytes))
}
}
6 changes: 4 additions & 2 deletions simulator/UT0311L04/UTC0311L04.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,10 @@ func unmarshal(bytes []byte, filepath string, compressed bool) (*UT0311L04, erro
Tasks: []types.Task{},
}

if err := json.Unmarshal(object.TaskList, &tasklist); err != nil {
warnf(object.SerialNumber, "error loading tasklist (%v)", err)
if object.TaskList != nil && len(object.TaskList) > 0 {
if err := json.Unmarshal(object.TaskList, &tasklist); err != nil {
warnf(object.SerialNumber, "error loading tasklist (%v)", err)
}
}

// ... initialise simulator
Expand Down
245 changes: 243 additions & 2 deletions simulator/UT0311L04/UTC0311L04_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,28 @@ func TestUT0311L04Unmarshal(t *testing.T) {
Doors: doors,
Keypads: map[uint8]entities.Keypad{1: 3, 2: 3, 3: 0, 4: 3},
TimeProfiles: entities.TimeProfiles{},
TaskList: entities.TaskList{},
Events: entities.NewEventList(),
TaskList: entities.TaskList{
Tasks: []types.Task{
types.Task{
Task: types.DoorNormallyClosed,
Door: 4,
From: types.MustParseDate("2024-01-01"),
To: types.MustParseDate("2024-12-31"),
Weekdays: types.Weekdays{
time.Sunday: false,
time.Monday: true,
time.Tuesday: false,
time.Wednesday: false,
time.Thursday: false,
time.Friday: true,
time.Saturday: false,
},
Start: types.NewHHmm(8, 30),
Cards: 0,
},
},
},
Events: entities.NewEventList(),
}

JSON := `
Expand Down Expand Up @@ -170,6 +190,10 @@ func TestUT0311L04Unmarshal(t *testing.T) {
if !reflect.DeepEqual(controller.Released, expected.Released) {
t.Errorf("incorrect firmware date - expected:%v, got:%v", expected.Released, controller.Released)
}

if !reflect.DeepEqual(controller.TaskList, expected.TaskList) {

Check failure on line 194 in simulator/UT0311L04/UTC0311L04_test.go

View workflow job for this annotation

GitHub Actions / Build

call of reflect.DeepEqual copies lock value: github.com/uhppoted/uhppote-simulator/entities.TaskList contains sync.Mutex

Check failure on line 194 in simulator/UT0311L04/UTC0311L04_test.go

View workflow job for this annotation

GitHub Actions / Build

call of reflect.DeepEqual copies lock value: github.com/uhppoted/uhppote-simulator/entities.TaskList contains sync.Mutex
t.Errorf("incorrect tasklist - expected:%v, got:%v", expected.TaskList, controller.TaskList)

Check failure on line 195 in simulator/UT0311L04/UTC0311L04_test.go

View workflow job for this annotation

GitHub Actions / Build

call of t.Errorf copies lock value: github.com/uhppoted/uhppote-simulator/entities.TaskList contains sync.Mutex

Check failure on line 195 in simulator/UT0311L04/UTC0311L04_test.go

View workflow job for this annotation

GitHub Actions / Build

call of t.Errorf copies lock value: github.com/uhppoted/uhppote-simulator/entities.TaskList contains sync.Mutex
}
}
}

Expand Down Expand Up @@ -198,6 +222,223 @@ func TestUT0311L04UnmarshalDefaultValues(t *testing.T) {
}
}

func TestUT0311L04UnmarshalWithMissingTaskList(t *testing.T) {
MAC, _ := net.ParseMAC("00:12:23:34:45:56")
doors := entities.MakeDoors()

expected := UT0311L04{
file: "test.json",
compressed: false,

SerialNumber: types.SerialNumber(405419896),
IpAddress: net.IPv4(0, 0, 0, 0),
SubnetMask: net.IPv4(255, 255, 255, 0),
Gateway: net.IPv4(0, 0, 0, 0),
MacAddress: types.MacAddress(MAC),
Version: 0x0892,
Released: types.MustParseDate("2018-11-05"),
Listener: netip.MustParseAddrPort("192.168.1.100:60001"),
Doors: doors,
Keypads: map[uint8]entities.Keypad{1: 3, 2: 3, 3: 0, 4: 3},
TimeProfiles: entities.TimeProfiles{},
TaskList: entities.TaskList{
Tasks: []types.Task{},
},
Events: entities.NewEventList(),
}

JSON := `
{
"serial-number": 405419896,
"address": "0.0.0.0",
"subnet": "255.255.255.0",
"gateway": "0.0.0.0",
"MAC": "00:12:23:34:45:56",
"version": "0892",
"released": "2018-11-05",
"offset": "-7h0m0.666172s",
"doors": {
"1": { "control": 3, "delay": "5s", "passcodes": [ 0, 0, 0, 0 ] },
"2": { "control": 3, "delay": "5s", "passcodes": [ 0, 0, 0, 0 ] },
"3": { "control": 3, "delay": "5s", "passcodes": [ 0, 0, 0, 0 ] },
"4": { "control": 3, "delay": "5s", "passcodes": [ 0, 0, 0, 0 ] },
"interlock": 4
},
"keypads": { "1": 3, "2": 3, "3": 0, "4": 3 },
"listener": "192.168.1.100:60001",
"record-special-events": true,
"pc-control": true,
"system-error": 0,
"sequence-id": 0,
"special-info": 0,
"input-state": 0,
"time-profiles": {
"100": {
"id": 100,
"start-date": "2023-04-01",
"end-date": "2023-12-31",
"weekdays": "Monday,Wednesday,Friday",
"segments": [
{ "start": "08:30", "end": "11:30" },
{ "start": "00:00", "end": "00:00" },
{ "start": "13:45", "end": "17:00" }
]
}
},
"cards": [],
"events": {
"size": 256,
"chunk": 8,
"index": 0,
"events": [
{ "index": 1, "type": 1, "granted": false, "door": 3, "direction": 1, "card": 10058400, "timestamp": "2024-05-08 10:50:53", "reason": 18 }
]
}
}
`

if controller, err := unmarshal([]byte(JSON), "test.json", false); err != nil {
t.Fatalf("error unmarshalling UT0311L04 (%v)", err)
} else if controller == nil {
t.Fatalf("error unmarshalling UT0311L04, expected UT0311L04{}, got %v", controller)
} else {
expected.touched = controller.touched

if controller.SerialNumber != expected.SerialNumber {
t.Errorf("incorrect serial number - expected:%v, got:%v", expected.SerialNumber, controller.SerialNumber)
}

if !reflect.DeepEqual(controller.IpAddress, expected.IpAddress) {
t.Errorf("incorrect IP address - expected:%v, got:%v", expected.IpAddress, controller.IpAddress)
}

if !reflect.DeepEqual(controller.SubnetMask, expected.SubnetMask) {
t.Errorf("incorrect netmask - expected:%v, got:%v", expected.SubnetMask, controller.SubnetMask)
}

if controller.Version != expected.Version {
t.Errorf("incorrect version - expected:%v, got:%v", expected.Version, controller.Version)
}

if !reflect.DeepEqual(controller.Released, expected.Released) {
t.Errorf("incorrect firmware date - expected:%v, got:%v", expected.Released, controller.Released)
}

if !reflect.DeepEqual(controller.TaskList, expected.TaskList) {

Check failure on line 327 in simulator/UT0311L04/UTC0311L04_test.go

View workflow job for this annotation

GitHub Actions / Build

call of reflect.DeepEqual copies lock value: github.com/uhppoted/uhppote-simulator/entities.TaskList contains sync.Mutex

Check failure on line 327 in simulator/UT0311L04/UTC0311L04_test.go

View workflow job for this annotation

GitHub Actions / Build

call of reflect.DeepEqual copies lock value: github.com/uhppoted/uhppote-simulator/entities.TaskList contains sync.Mutex
t.Errorf("incorrect tasklist - expected:%v, got:%v", expected.TaskList, controller.TaskList)

Check failure on line 328 in simulator/UT0311L04/UTC0311L04_test.go

View workflow job for this annotation

GitHub Actions / Build

call of t.Errorf copies lock value: github.com/uhppoted/uhppote-simulator/entities.TaskList contains sync.Mutex

Check failure on line 328 in simulator/UT0311L04/UTC0311L04_test.go

View workflow job for this annotation

GitHub Actions / Build

call of t.Errorf copies lock value: github.com/uhppoted/uhppote-simulator/entities.TaskList contains sync.Mutex
}
}
}

func TestUT0311L04UnmarshalWithInvalidTaskList(t *testing.T) {
MAC, _ := net.ParseMAC("00:12:23:34:45:56")
doors := entities.MakeDoors()

expected := UT0311L04{
file: "test.json",
compressed: false,

SerialNumber: types.SerialNumber(405419896),
IpAddress: net.IPv4(0, 0, 0, 0),
SubnetMask: net.IPv4(255, 255, 255, 0),
Gateway: net.IPv4(0, 0, 0, 0),
MacAddress: types.MacAddress(MAC),
Version: 0x0892,
Released: types.MustParseDate("2018-11-05"),
Listener: netip.MustParseAddrPort("192.168.1.100:60001"),
Doors: doors,
Keypads: map[uint8]entities.Keypad{1: 3, 2: 3, 3: 0, 4: 3},
TimeProfiles: entities.TimeProfiles{},
TaskList: entities.TaskList{
Tasks: []types.Task{},
},
Events: entities.NewEventList(),
}

JSON := `
{
"serial-number": 405419896,
"address": "0.0.0.0",
"subnet": "255.255.255.0",
"gateway": "0.0.0.0",
"MAC": "00:12:23:34:45:56",
"version": "0892",
"released": "2018-11-05",
"offset": "-7h0m0.666172s",
"doors": {
"1": { "control": 3, "delay": "5s", "passcodes": [ 0, 0, 0, 0 ] },
"2": { "control": 3, "delay": "5s", "passcodes": [ 0, 0, 0, 0 ] },
"3": { "control": 3, "delay": "5s", "passcodes": [ 0, 0, 0, 0 ] },
"4": { "control": 3, "delay": "5s", "passcodes": [ 0, 0, 0, 0 ] },
"interlock": 4
},
"keypads": { "1": 3, "2": 3, "3": 0, "4": 3 },
"listener": "192.168.1.100:60001",
"record-special-events": true,
"pc-control": true,
"system-error": 0,
"sequence-id": 0,
"special-info": 0,
"input-state": 0,
"time-profiles": {
"100": {
"id": 100,
"start-date": "2023-04-01",
"end-date": "2023-12-31",
"weekdays": "Monday,Wednesday,Friday",
"segments": [
{ "start": "08:30", "end": "11:30" },
{ "start": "00:00", "end": "00:00" },
{ "start": "13:45", "end": "17:00" }
]
}
},
"tasklist": "notasksheremovealong",
"cards": [],
"events": {
"size": 256,
"chunk": 8,
"index": 0,
"events": [
{ "index": 1, "type": 1, "granted": false, "door": 3, "direction": 1, "card": 10058400, "timestamp": "2024-05-08 10:50:53", "reason": 18 }
]
}
}
`

if controller, err := unmarshal([]byte(JSON), "test.json", false); err != nil {
t.Fatalf("error unmarshalling UT0311L04 (%v)", err)
} else if controller == nil {
t.Fatalf("error unmarshalling UT0311L04, expected UT0311L04{}, got %v", controller)
} else {
expected.touched = controller.touched

if controller.SerialNumber != expected.SerialNumber {
t.Errorf("incorrect serial number - expected:%v, got:%v", expected.SerialNumber, controller.SerialNumber)
}

if !reflect.DeepEqual(controller.IpAddress, expected.IpAddress) {
t.Errorf("incorrect IP address - expected:%v, got:%v", expected.IpAddress, controller.IpAddress)
}

if !reflect.DeepEqual(controller.SubnetMask, expected.SubnetMask) {
t.Errorf("incorrect netmask - expected:%v, got:%v", expected.SubnetMask, controller.SubnetMask)
}

if controller.Version != expected.Version {
t.Errorf("incorrect version - expected:%v, got:%v", expected.Version, controller.Version)
}

if !reflect.DeepEqual(controller.Released, expected.Released) {
t.Errorf("incorrect firmware date - expected:%v, got:%v", expected.Released, controller.Released)
}

if !reflect.DeepEqual(controller.TaskList, expected.TaskList) {
t.Errorf("incorrect tasklist - expected:%v, got:%v", expected.TaskList, controller.TaskList)
}
}
}

func testHandle(request messages.Request, expected messages.Response, t *testing.T) {
MAC, _ := net.ParseMAC("00:66:19:39:55:2d")
from := types.MustParseDate("2019-01-01")
Expand Down

0 comments on commit 3f23371

Please sign in to comment.