From 07c78387d806a0d0adc2e2270021dfacfea56ee0 Mon Sep 17 00:00:00 2001 From: Noah Metz Date: Sat, 8 Apr 2023 15:23:40 -0600 Subject: [PATCH] Added tests for graph.go --- graph.go | 38 +++++++++++-- graph_test.go | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+), 4 deletions(-) create mode 100644 graph_test.go diff --git a/graph.go b/graph.go index a66fef6..f30c8b8 100644 --- a/graph.go +++ b/graph.go @@ -137,7 +137,6 @@ type Resource interface { type BaseResource struct { BaseNode - update_channel chan error parents []Resource children []Resource } @@ -153,7 +152,7 @@ func (resource * BaseResource) Parents() []Resource { func (resource * BaseResource) AddParent(parent Resource) error { // Don't add self as parent if parent.ID() == resource.ID() { - error_str := fmt.Sprintf("Will not add %s as parent of itself", parent.ID) + error_str := fmt.Sprintf("Will not add %s as parent of itself", parent.ID()) return errors.New(error_str) } @@ -190,7 +189,22 @@ type BaseEvent struct { parent Event } -func NewBaseEvent(name string, description string, required_resources []Resource) * BaseEvent { +func NewResource(name string, description string, children []Resource) * BaseResource { + resource := &BaseResource{ + BaseNode: BaseNode{ + name: name, + description: description, + id: gql_randid(), + listeners: []chan error{}, + }, + parents: []Resource{}, + children: children, + } + + return resource +} + +func NewEvent(name string, description string, required_resources []Resource) * BaseEvent { event := &BaseEvent{ BaseNode: BaseNode{ name: name, @@ -199,6 +213,7 @@ func NewBaseEvent(name string, description string, required_resources []Resource listeners: []chan error{}, }, parent: nil, + children: []Event{}, locked_resources: []Resource{}, created_resources: []Resource{}, required_resources: required_resources, @@ -272,10 +287,25 @@ func NewEventManager() * EventManager { return state; } +func (manager * EventManager) FindResource(id graphql.ID) Resource { + resource, exists := manager.dag_nodes[id] + if exists == false { + return nil + } + + return resource +} + +func (manager * EventManager) FindEvent(id graphql.ID) Event { + event := manager.root_event.FindChild(id) + + return event +} + func (manager * EventManager) AddResource(resource Resource) error { _, exists := manager.dag_nodes[resource.ID()] if exists == true { - error_str := fmt.Sprintf("%s is already in the resource DAG, cannot add again") + error_str := fmt.Sprintf("%s is already in the resource DAG, cannot add again", resource.ID()) return errors.New(error_str) } diff --git a/graph_test.go b/graph_test.go new file mode 100644 index 0000000..d44b83b --- /dev/null +++ b/graph_test.go @@ -0,0 +1,155 @@ +package main + +import ( + "testing" + "time" +) + +type graph_tester testing.T +const listner_timeout = 100 * time.Millisecond + +func (t * graph_tester) CheckForNil(listener chan error) { + timeout := time.After(listner_timeout) + select { + case msg := <-listener: + if msg == nil { + return + } else { + t.Fatal("non-nil message on channel") + } + case <-timeout: + t.Fatal("timeout waiting for message on channel") + } +} + +func (t * graph_tester) CheckForNonNil(listener chan error) { + timeout := time.After(listner_timeout) + select { + case msg := <- listener: + if msg != nil { + return + } else { + t.Fatal("nil message on channel") + } + case <-timeout: + t.Fatal("timeout waiting for message on channel") + } +} + +func (t * graph_tester) CheckForNone(listener chan error) { + timeout := time.After(listner_timeout) + select { + case <- listener: + t.Fatal("message on channel") + case <-timeout: + } +} + +func TestNewResourceAdd(t *testing.T) { + name := "Test Resource" + description := "A resource for testing" + children := []Resource{} + + test_resource := NewResource(name, description, children) + event_manager := NewEventManager() + event_manager.AddResource(test_resource) + 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) { + test_resource := NewResource("", "", []Resource{}) + event_manager := NewEventManager() + err_1 := event_manager.AddResource(test_resource) + err_2 := event_manager.AddResource(test_resource) + + if err_1 != nil { + t.Fatalf("First AddResource returned error %s", err_1) + } + + if err_2 == nil { + t.Fatal("Second AddResource returned nil") + } +} + +func TestMissingResourceAdd(t * testing.T) { + r1 := NewResource("r1", "", []Resource{}) + r2 := NewResource("r2", "", []Resource{r1}) + + event_manager := NewEventManager() + err := event_manager.AddResource(r2) + if err == nil { + t.Fatal("AddResource with missing child returned nil") + } +} + +func TestTieredResourceAdd(t * testing.T) { + r1 := NewResource("r1", "", []Resource{}) + r2 := NewResource("r2", "", []Resource{r1}) + + event_manager := NewEventManager() + err_1 := event_manager.AddResource(r1) + err_2 := event_manager.AddResource(r2) + if err_1 != nil || err_2 != nil { + t.Fatal("Failed adding tiered resource") + } +} + +func TestResourceUpdate(t * testing.T) { + r1 := NewResource("r1", "", []Resource{}) + r2 := NewResource("r2", "", []Resource{}) + r3 := NewResource("r3", "", []Resource{r1, r2}) + + event_manager := NewEventManager() + err_1 := event_manager.AddResource(r1) + err_2 := event_manager.AddResource(r2) + err_3 := event_manager.AddResource(r3) + + if err_1 != nil || err_2 != nil || err_3 != nil { + t.Fatal("Failed to add initial tiered resources for test") + } + + r1_l := r1.UpdateChannel() + r2_l := r2.UpdateChannel() + r3_l := r3.UpdateChannel() + + // Calling Update() on the parent with no other parents should only notify node listeners + r3.Update() + (*graph_tester)(t).CheckForNone(r1_l) + (*graph_tester)(t).CheckForNone(r2_l) + (*graph_tester)(t).CheckForNil(r3_l) + + // Calling Update() on a child should notify listeners of the parent and child, but not siblings + r2.Update() + (*graph_tester)(t).CheckForNone(r1_l) + (*graph_tester)(t).CheckForNil(r2_l) + (*graph_tester)(t).CheckForNil(r3_l) + + // Calling Update() on a child should notify listeners of the parent and child, but not siblings + r1.Update() + (*graph_tester)(t).CheckForNil(r1_l) + (*graph_tester)(t).CheckForNone(r2_l) + (*graph_tester)(t).CheckForNil(r3_l) +} + +func TestLockResource(t * testing.T) { + r1 := NewResource("r1", "", []Resource{}) + r2 := NewResource("r2", "", []Resource{}) + r3 := NewResource("r3", "", []Resource{r1, r2}) + + event_manager := NewEventManager() + err_1 := event_manager.AddResource(r1) + err_2 := event_manager.AddResource(r2) + err_3 := event_manager.AddResource(r3) + + if err_1 != nil || err_2 != nil || err_3 != nil { + t.Fatal("Failed to add initial tiered resources for test") + } +}