graphvent/manager_test.go

421 lines
13 KiB
Go

2023-04-08 15:23:40 -06:00
package main
import (
"testing"
"time"
2023-05-29 23:54:52 -06:00
"fmt"
2023-06-03 18:56:14 -06:00
"os"
"runtime/pprof"
2023-04-08 15:23:40 -06:00
)
type graph_tester testing.T
const listner_timeout = 50 * time.Millisecond
2023-04-08 15:23:40 -06:00
2023-06-03 18:56:14 -06:00
func (t * graph_tester) WaitForValue(listener chan GraphSignal, signal_type string, source GraphNode, timeout time.Duration, str string) GraphSignal {
2023-06-03 02:07:16 -06:00
timeout_channel := time.After(timeout)
for true {
select {
case signal := <- listener:
if signal.Type() == signal_type {
2023-06-03 18:56:14 -06:00
if signal.Source() == nil || source == nil {
fmt.Printf("SIGNAL_TYPE_FOUND: %s - %s", signal.Type(), signal.Source())
if source == nil && signal.Source() == nil{
return signal
}
} else {
fmt.Printf("SIGNAL_TYPE_FOUND: %s - %s", signal.Type(), signal.Source().Name())
if signal.Source().ID() == source.ID() {
return signal
}
}
2023-06-03 02:07:16 -06:00
}
case <-timeout_channel:
2023-06-03 18:56:14 -06:00
pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
2023-06-03 02:07:16 -06:00
t.Fatal(str)
return nil
}
}
return nil
}
func (t * graph_tester) CheckForValue(listener chan GraphSignal, str string) GraphSignal {
2023-04-08 15:23:40 -06:00
timeout := time.After(listner_timeout)
select {
2023-06-03 02:07:16 -06:00
case signal := <- listener:
return signal
2023-04-08 15:23:40 -06:00
case <-timeout:
2023-06-03 18:56:14 -06:00
pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
t.Fatal(str)
2023-06-03 02:07:16 -06:00
return nil
2023-04-08 15:23:40 -06:00
}
}
func (t * graph_tester) CheckForNone(listener chan GraphSignal, str string) {
2023-04-08 15:23:40 -06:00
timeout := time.After(listner_timeout)
select {
2023-06-03 01:38:35 -06:00
case sig := <- listener:
2023-06-03 18:56:14 -06:00
pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
t.Fatal(fmt.Sprintf("%s : %+v", str, sig))
2023-06-03 01:38:35 -06:00
case <-timeout:
2023-04-08 15:23:40 -06:00
}
}
func TestNewResourceAdd(t *testing.T) {
name := "Test Resource"
description := "A resource for testing"
children := []Resource{}
2023-05-29 23:54:52 -06:00
root_event := NewEvent("", "", []Resource{})
2023-04-08 15:23:40 -06:00
test_resource := NewResource(name, description, children)
event_manager := NewEventManager(root_event, []Resource{test_resource})
2023-04-08 15:23:40 -06:00
res := event_manager.FindResource(test_resource.ID())
if res == nil {
t.Fatal("Failed to find Resource in EventManager after adding")
}
if res.Name() != name || res.Description() != description {
t.Fatal("Name/description of returned resource did not match added resource")
}
}
func TestDoubleResourceAdd(t * testing.T) {
2023-05-29 23:54:52 -06:00
root_event := NewEvent("", "", []Resource{})
2023-04-08 15:23:40 -06:00
test_resource := NewResource("", "", []Resource{})
event_manager := NewEventManager(root_event, []Resource{test_resource})
err := event_manager.AddResource(test_resource)
2023-04-08 15:23:40 -06:00
if err == nil {
2023-04-08 15:23:40 -06:00
t.Fatal("Second AddResource returned nil")
}
}
func TestMissingResourceAdd(t * testing.T) {
2023-05-29 23:54:52 -06:00
root_event := NewEvent("", "", []Resource{})
2023-04-08 15:23:40 -06:00
r1 := NewResource("r1", "", []Resource{})
r2 := NewResource("r2", "", []Resource{r1})
event_manager := NewEventManager(root_event, []Resource{})
2023-04-08 15:23:40 -06:00
err := event_manager.AddResource(r2)
if err == nil {
t.Fatal("AddResource with missing child returned nil")
}
}
func TestTieredResource(t * testing.T) {
2023-05-29 23:54:52 -06:00
root_event := NewEvent("", "", []Resource{})
2023-04-08 15:23:40 -06:00
r1 := NewResource("r1", "", []Resource{})
r2 := NewResource("r2", "", []Resource{r1})
event_manager := NewEventManager(root_event, []Resource{r1, r2})
if event_manager == nil {
t.Fatal("Failed to create event manager with tiered resources")
2023-04-08 15:23:40 -06:00
}
}
func TestResourceUpdate(t * testing.T) {
2023-05-29 23:54:52 -06:00
root_event := NewEvent("", "", []Resource{})
2023-04-08 15:23:40 -06:00
r1 := NewResource("r1", "", []Resource{})
r2 := NewResource("r2", "", []Resource{})
r3 := NewResource("r3", "", []Resource{r1, r2})
2023-04-08 15:26:04 -06:00
r4 := NewResource("r4", "", []Resource{r3})
2023-04-08 15:23:40 -06:00
event_manager := NewEventManager(root_event, []Resource{r1, r2, r3, r4})
if event_manager == nil {
2023-04-08 15:23:40 -06:00
t.Fatal("Failed to add initial tiered resources for test")
}
r1_l := r1.UpdateChannel()
r2_l := r2.UpdateChannel()
r3_l := r3.UpdateChannel()
2023-04-08 15:26:04 -06:00
r4_l := r4.UpdateChannel()
2023-04-08 15:23:40 -06:00
// Calling Update() on the parent with no other parents should only notify node listeners
SendUpdate(r3, NewSignal(nil, "test"))
(*graph_tester)(t).CheckForNone(r1_l, "Update on r1 after updating r3")
(*graph_tester)(t).CheckForNone(r2_l, "Update on r2 after updating r3")
(*graph_tester)(t).CheckForValue(r3_l, "No update on r3 after updating r3")
(*graph_tester)(t).CheckForValue(r4_l, "No update on r4 after updating r3")
2023-04-08 15:23:40 -06:00
// Calling Update() on a child should notify listeners of the parent and child, but not siblings
SendUpdate(r2, NewSignal(nil, "test"))
(*graph_tester)(t).CheckForNone(r1_l, "Update on r1 after updating r2")
(*graph_tester)(t).CheckForValue(r2_l, "No update on r2 after updating r2")
(*graph_tester)(t).CheckForValue(r3_l, "No update on r3 after updating r2")
(*graph_tester)(t).CheckForValue(r4_l, "No update on r4 after updating r2")
2023-04-08 15:23:40 -06:00
// Calling Update() on a child should notify listeners of the parent and child, but not siblings
SendUpdate(r1, NewSignal(nil, "test"))
(*graph_tester)(t).CheckForValue(r1_l, "No update on r1 after updating r1")
(*graph_tester)(t).CheckForNone(r2_l, "Update on r2 after updating r1")
(*graph_tester)(t).CheckForValue(r3_l, "No update on r3 after updating r1")
(*graph_tester)(t).CheckForValue(r4_l, "No update on r4 after updating r1")
2023-04-08 15:23:40 -06:00
}
func TestAddEvent(t * testing.T) {
2023-05-29 23:54:52 -06:00
root_event := NewEvent("", "", []Resource{})
2023-04-08 16:59:36 -06:00
r1 := NewResource("r1", "", []Resource{})
r2 := NewResource("r2", "", []Resource{r1})
name := "Test Event"
description := "A test event"
resources := []Resource{r2}
2023-05-29 23:54:52 -06:00
new_event := NewEvent(name, description, resources)
2023-04-08 16:59:36 -06:00
event_manager := NewEventManager(root_event, []Resource{r1})
err := event_manager.AddResource(r2)
if err != nil {
t.Fatal("Failed to add r2 to event_manager")
}
err = event_manager.AddEvent(root_event, new_event, nil)
2023-04-08 16:59:36 -06:00
if err != nil {
t.Fatalf("Failed to add new_event to root_event: %s", err)
}
res := event_manager.FindEvent(new_event.ID())
if res == nil {
t.Fatalf("Failed to find new_event in event_manager: %s", err)
}
2023-04-08 16:59:36 -06:00
if res.Name() != name || res.Description() != description {
t.Fatal("Event found in event_manager didn't match added")
}
res_required := res.RequiredResources()
if len(res_required) < 1 {
t.Fatal("Event found in event_manager didn't match added")
} else if res_required[0].ID() != r2.ID() {
t.Fatal("Event found in event_manager didn't match added")
}
}
2023-04-08 15:23:40 -06:00
func TestLockResource(t * testing.T) {
2023-05-29 23:54:52 -06:00
root_event := NewEvent("", "", []Resource{})
test_event := NewEvent("", "", []Resource{})
2023-04-08 15:23:40 -06:00
r1 := NewResource("r1", "", []Resource{})
r2 := NewResource("r2", "", []Resource{})
r3 := NewResource("r3", "", []Resource{r1, r2})
r4 := NewResource("r4", "", []Resource{r1, r2})
2023-04-08 15:23:40 -06:00
event_manager := NewEventManager(root_event, []Resource{r1, r2, r3, r4})
2023-04-08 15:23:40 -06:00
if event_manager == nil {
2023-04-08 15:23:40 -06:00
t.Fatal("Failed to add initial tiered resources for test")
}
r1_l := r1.UpdateChannel()
rel := root_event.UpdateChannel()
err := LockResource(r3, root_event)
if err != nil {
t.Fatal("Failed to lock r3")
}
NotifyResourceLocked(r3)
2023-06-03 18:56:14 -06:00
(*graph_tester)(t).WaitForValue(r1_l, "lock_changed", r1, time.Second, "Wasn't notified of r1 lock on r1 after r3 lock")
(*graph_tester)(t).WaitForValue(rel, "lock_changed", r1, time.Second, "Wasn't notified of r1 lock on rel after r3 lock")
err = LockResource(r3, root_event)
if err == nil {
t.Fatal("Locked r3 after locking r3")
}
err = LockResource(r4, root_event)
if err == nil {
t.Fatal("Locked r4 after locking r3")
}
err = LockResource(r1, root_event)
if err == nil {
t.Fatal("Locked r1 after locking r3")
}
err = UnlockResource(r3, test_event)
if err == nil {
t.Fatal("Unlocked r3 with event that didn't lock it")
}
err = UnlockResource(r3, root_event)
if err != nil {
t.Fatal("Failed to unlock r3")
}
NotifyResourceUnlocked(r3)
2023-06-03 18:56:14 -06:00
(*graph_tester)(t).WaitForValue(r1_l, "lock_changed", r1, time.Second * 2, "Wasn't notified of r1 unlock on r1 after r3 unlock")
err = LockResource(r4, root_event)
if err != nil {
t.Fatal("Failed to lock r4 after unlocking r3")
}
NotifyResourceLocked(r4)
2023-06-03 18:56:14 -06:00
(*graph_tester)(t).WaitForValue(r1_l, "lock_changed", r1, time.Second * 2, "Wasn't notified of r1 lock on r1 after r4 lock")
(*graph_tester)(t).WaitForValue(rel, "lock_changed", r1, time.Second * 2, "Wasn't notified of r1 lock on r1 after r4 lock")
err = UnlockResource(r4, root_event)
if err != nil {
t.Fatal("Failed to unlock r4")
}
NotifyResourceUnlocked(r4)
2023-06-03 18:56:14 -06:00
(*graph_tester)(t).WaitForValue(r1_l, "lock_changed", r1, time.Second * 2, "Wasn't notified of r1 unlock on r1 after r4 lock")
2023-04-08 15:23:40 -06:00
}
func TestAddToEventQueue(t * testing.T) {
2023-05-29 23:54:52 -06:00
queue := NewEventQueue("q", "", []Resource{})
event_1 := NewEvent("1", "", []Resource{})
event_2 := NewEvent("2", "", []Resource{})
err := AddChild(queue, event_1, nil)
if err == nil {
t.Fatal("suceeded in added nil info to queue")
}
err = AddChild(queue, event_1, &EventQueueInfo{priority: 0})
if err != nil {
t.Fatal("failed to add valid event + info to queue")
}
err = AddChild(queue, event_2, &EventQueueInfo{priority: 1})
if err != nil {
t.Fatal("failed to add valid event + info to queue")
}
}
func TestStartBaseEvent(t * testing.T) {
event_1 := NewEvent("TestStartBaseEvent event_1", "", []Resource{})
2023-05-29 23:54:52 -06:00
r := event_1.DoneResource()
manager := NewEventManager(event_1, []Resource{})
e_l := event_1.UpdateChannel()
r_l := r.UpdateChannel()
(*graph_tester)(t).CheckForNone(e_l, "Update on event_1 before starting")
(*graph_tester)(t).CheckForNone(r_l, "Update on r_1 before starting")
if r.Owner().ID() != event_1.ID() {
t.Fatal("r is not owned by event_1")
}
2023-05-29 23:54:52 -06:00
err := manager.Run()
if err != nil {
t.Fatal(err)
}
// Check that the update channels for the event and resource have updates
(*graph_tester)(t).CheckForValue(e_l, "No update on event_1 after starting")
(*graph_tester)(t).CheckForValue(r_l, "No update on r_l after starting")
if r.Owner() != nil {
t.Fatal("r still owned after event completed")
}
}
2023-05-29 23:54:52 -06:00
func TestAbortEventQueue(t * testing.T) {
root_event := NewEventQueue("", "", []Resource{})
r := root_event.DoneResource()
manager := NewEventManager(root_event, []Resource{})
r1 := NewResource("r1", "", []Resource{})
err := manager.AddResource(r1)
if err != nil {
t.Fatal(err)
}
LockResource(r1, root_event)
2023-05-29 23:54:52 -06:00
e1 := NewEvent("1", "", []Resource{r1})
e1_info := NewEventQueueInfo(1)
// Add an event so that the queue doesn't auto complete
err = manager.AddEvent(root_event, e1, e1_info)
if err != nil {
t.Fatal(err)
}
// Now that an event manager is constructed with a queue and 3 basic events
// start the queue and check that all the events are executed
go func() {
2023-06-02 17:39:28 -06:00
time.Sleep(100 * time.Millisecond)
AbortEvent(root_event)
2023-05-29 23:54:52 -06:00
}()
err = manager.Run()
if err == nil {
t.Fatal("event manager completed without error")
}
if r.Owner() == nil {
t.Fatal("root event was finished after starting")
}
}
func TestStartEventQueue(t * testing.T) {
root_event := NewEventQueue("root_event", "", []Resource{})
2023-05-29 23:54:52 -06:00
r := root_event.DoneResource()
rel := root_event.UpdateChannel();
res_1 := NewResource("test_resource_1", "", []Resource{})
res_2 := NewResource("test_resource_2", "", []Resource{})
manager := NewEventManager(root_event, []Resource{res_1, res_2})
e1:= NewEvent("e1", "", []Resource{res_1, res_2})
2023-05-29 23:54:52 -06:00
e1_r := e1.DoneResource()
e1_info := NewEventQueueInfo(1)
err := manager.AddEvent(root_event, e1, e1_info)
if err != nil {
t.Fatal("Failed to add e1 to manager")
}
(*graph_tester)(t).CheckForValue(rel, "No update on root_event after adding e1")
e2 := NewEvent("e2", "", []Resource{res_1})
2023-05-29 23:54:52 -06:00
e2_r := e2.DoneResource()
e2_info := NewEventQueueInfo(2)
err = manager.AddEvent(root_event, e2, e2_info)
if err != nil {
t.Fatal("Failed to add e2 to manager")
}
(*graph_tester)(t).CheckForValue(rel, "No update on root_event after adding e2")
e3 := NewEvent("e3", "", []Resource{res_2})
2023-05-29 23:54:52 -06:00
e3_r := e3.DoneResource()
e3_info := NewEventQueueInfo(3)
err = manager.AddEvent(root_event, e3, e3_info)
if err != nil {
t.Fatal("Failed to add e3 to manager")
}
(*graph_tester)(t).CheckForValue(rel, "No update on root_event after adding e3")
e1_l := e1.UpdateChannel();
e2_l := e2.UpdateChannel();
e3_l := e3.UpdateChannel();
2023-05-29 23:54:52 -06:00
// Abort the event after 5 seconds just in case
go func() {
time.Sleep(5 * time.Second)
if r.Owner() != nil {
AbortEvent(root_event)
}
2023-05-29 23:54:52 -06:00
}()
// Now that an event manager is constructed with a queue and 3 basic events
// start the queue and check that all the events are executed
2023-05-29 23:54:52 -06:00
err = manager.Run()
if err != nil {
t.Fatal(err)
}
if r.Owner() != nil {
2023-05-29 23:54:52 -06:00
fmt.Printf("root_event.DoneResource(): %p", root_event.DoneResource())
t.Fatal("root event was not finished after starting")
}
2023-06-03 18:56:14 -06:00
(*graph_tester)(t).WaitForValue(e1_l, "event_done", e1, time.Second, "no e1 event_done")
if e1_r.Owner() != nil {
t.Fatal("e1 was not completed")
}
2023-06-03 18:56:14 -06:00
(*graph_tester)(t).WaitForValue(e2_l, "event_done", e2, time.Second, "no e2 event_done")
if e2_r.Owner() != nil {
2023-06-03 18:56:14 -06:00
t.Fatal(fmt.Sprintf("e2 was not completed"))
}
2023-06-03 18:56:14 -06:00
(*graph_tester)(t).WaitForValue(e3_l, "event_done", e3, time.Second, "no e3 event_done")
if e3_r.Owner() != nil {
t.Fatal("e3 was not completed")
}
}