Updated tests and fixed updates before/after locking/unlocking

graph-rework
noah metz 2023-06-01 13:48:38 -06:00
parent 990b93757f
commit d7b13de82f
5 changed files with 101 additions and 68 deletions

@ -133,14 +133,19 @@ func (event * BaseEvent) LockResources() error {
} }
func (event * BaseEvent) Finish() error { func (event * BaseEvent) Finish() error {
log.Printf("EVENT_FINISH: %s", event.Name())
for _, resource := range(event.RequiredResources()) { for _, resource := range(event.RequiredResources()) {
err := resource.Unlock(event) err := resource.Unlock(event)
if err != nil { if err != nil {
panic(err) panic(err)
} }
resource.Update("unlocking after event finish") resource.NotifyUnlocked()
} }
return event.DoneResource().Unlock(event) err := event.DoneResource().Unlock(event)
if err != nil {
return err
}
return event.DoneResource().NotifyUnlocked()
} }
func (event * BaseEvent) LockDone() { func (event * BaseEvent) LockDone() {
@ -180,10 +185,6 @@ func (event * BaseEvent) Run() error {
event.Update(update_str) event.Update(update_str)
} }
err = event.DoneResource().Unlock(event)
if err != nil {
return err
}
return nil return nil
} }

@ -38,6 +38,7 @@ func NewEventManager(root_event Event, dag_nodes []Resource) * EventManager {
// Connect to all resources(in a thread to handle reconnections), and start the first event // Connect to all resources(in a thread to handle reconnections), and start the first event
func (manager * EventManager) Run() error { func (manager * EventManager) Run() error {
log.Printf("MANAGER_START")
aborts := []chan error{} aborts := []chan error{}
for _, resource := range(manager.dag_nodes) { for _, resource := range(manager.dag_nodes) {
abort := make(chan error, 1) abort := make(chan error, 1)
@ -54,12 +55,23 @@ func (manager * EventManager) Run() error {
c <- nil c <- nil
} }
}(abort, aborts) }(abort, aborts)
err := manager.root_event.Run() err := manager.root_event.LockResources()
if err != nil {
return err
}
err = manager.root_event.Run()
abort <- nil abort <- nil
if err != nil { if err != nil {
return err return err
} }
err = manager.root_event.Finish()
if err != nil {
return err
}
log.Printf("MANAGER_DONE")
return nil return nil
} }

@ -9,39 +9,21 @@ import (
type graph_tester testing.T type graph_tester testing.T
const listner_timeout = 100 * time.Millisecond const listner_timeout = 100 * time.Millisecond
func (t * graph_tester) CheckForNil(listener chan error) { func (t * graph_tester) CheckForValue(listener chan string, str string) {
timeout := time.After(listner_timeout) timeout := time.After(listner_timeout)
select { select {
case msg := <-listener: case <- listener:
if msg == nil { return
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: case <-timeout:
t.Fatal("timeout waiting for message on channel") t.Fatal(str)
} }
} }
func (t * graph_tester) CheckForNone(listener chan error) { func (t * graph_tester) CheckForNone(listener chan string, str string) {
timeout := time.After(listner_timeout) timeout := time.After(listner_timeout)
select { select {
case <- listener: case <- listener:
t.Fatal("message on channel") t.Fatal(str)
case <-timeout: case <-timeout:
} }
} }
@ -117,25 +99,25 @@ func TestResourceUpdate(t * testing.T) {
r4_l := r4.UpdateChannel() r4_l := r4.UpdateChannel()
// Calling Update() on the parent with no other parents should only notify node listeners // Calling Update() on the parent with no other parents should only notify node listeners
r3.Update() r3.Update("test")
(*graph_tester)(t).CheckForNone(r1_l) (*graph_tester)(t).CheckForNone(r1_l, "Update on r1 after updating r3")
(*graph_tester)(t).CheckForNone(r2_l) (*graph_tester)(t).CheckForNone(r2_l, "Update on r2 after updating r3")
(*graph_tester)(t).CheckForNil(r3_l) (*graph_tester)(t).CheckForValue(r3_l, "No update on r3 after updating r3")
(*graph_tester)(t).CheckForNil(r4_l) (*graph_tester)(t).CheckForValue(r4_l, "No update on r4 after updating r3")
// Calling Update() on a child should notify listeners of the parent and child, but not siblings // Calling Update() on a child should notify listeners of the parent and child, but not siblings
r2.Update() r2.Update("test")
(*graph_tester)(t).CheckForNone(r1_l) (*graph_tester)(t).CheckForNone(r1_l, "Update on r1 after updating r2")
(*graph_tester)(t).CheckForNil(r2_l) (*graph_tester)(t).CheckForValue(r2_l, "No update on r2 after updating r2")
(*graph_tester)(t).CheckForNil(r3_l) (*graph_tester)(t).CheckForValue(r3_l, "No update on r3 after updating r2")
(*graph_tester)(t).CheckForNil(r4_l) (*graph_tester)(t).CheckForValue(r4_l, "No update on r4 after updating r2")
// Calling Update() on a child should notify listeners of the parent and child, but not siblings // Calling Update() on a child should notify listeners of the parent and child, but not siblings
r1.Update() r1.Update("test")
(*graph_tester)(t).CheckForNil(r1_l) (*graph_tester)(t).CheckForValue(r1_l, "No update on r1 after updating r1")
(*graph_tester)(t).CheckForNone(r2_l) (*graph_tester)(t).CheckForNone(r2_l, "Update on r2 after updating r1")
(*graph_tester)(t).CheckForNil(r3_l) (*graph_tester)(t).CheckForValue(r3_l, "No update on r3 after updating r1")
(*graph_tester)(t).CheckForNil(r4_l) (*graph_tester)(t).CheckForValue(r4_l, "No update on r4 after updating r1")
} }
func TestAddEvent(t * testing.T) { func TestAddEvent(t * testing.T) {
@ -197,8 +179,14 @@ func TestLockResource(t * testing.T) {
if err != nil { if err != nil {
t.Fatal("Failed to lock r3") t.Fatal("Failed to lock r3")
} }
(*graph_tester)(t).CheckForNil(r1_l)
(*graph_tester)(t).CheckForNil(rel) err = r3.NotifyLocked()
if err != nil {
t.Fatal("Failed to notify r3 of lock")
}
(*graph_tester)(t).CheckForValue(r1_l, "No value on r1 update channel")
(*graph_tester)(t).CheckForValue(rel, "No value on root_event update channel")
err = r3.Lock(root_event) err = r3.Lock(root_event)
if err == nil { if err == nil {
@ -224,22 +212,38 @@ func TestLockResource(t * testing.T) {
if err != nil { if err != nil {
t.Fatal("Failed to unlock r3") t.Fatal("Failed to unlock r3")
} }
(*graph_tester)(t).CheckForNil(r1_l)
(*graph_tester)(t).CheckForNil(rel) err = r3.NotifyUnlocked()
if err != nil {
t.Fatal("Failed to notify r3 it was unlocked")
}
(*graph_tester)(t).CheckForValue(r1_l, "No update on r1 after unlocking r3")
(*graph_tester)(t).CheckForValue(rel, "No update on rel after unlocking r3")
err = r4.Lock(root_event) err = r4.Lock(root_event)
if err != nil { if err != nil {
t.Fatal("Failed to lock r4 after unlocking r3") t.Fatal("Failed to lock r4 after unlocking r3")
} }
(*graph_tester)(t).CheckForNil(r1_l)
(*graph_tester)(t).CheckForNil(rel) err = r4.NotifyLocked()
if err != nil {
t.Fatal("Failed to notify r4 it was locked")
}
(*graph_tester)(t).CheckForValue(r1_l, "No update on r1 after locking r4")
(*graph_tester)(t).CheckForValue(rel, "No update on rel after locking r4")
err = r4.Unlock(root_event) err = r4.Unlock(root_event)
if err != nil { if err != nil {
t.Fatal("Failed to unlock r4") t.Fatal("Failed to unlock r4")
} }
(*graph_tester)(t).CheckForNil(r1_l)
(*graph_tester)(t).CheckForNil(rel) err = r4.NotifyUnlocked()
if err != nil {
t.Fatal("Failed to notify r4 it was unlocked")
}
(*graph_tester)(t).CheckForValue(r1_l, "No update on r1 after unlocking r4")
(*graph_tester)(t).CheckForValue(rel, "No update on rel after unlocking r4")
} }
func TestAddToEventQueue(t * testing.T) { func TestAddToEventQueue(t * testing.T) {
@ -270,8 +274,8 @@ func TestStartBaseEvent(t * testing.T) {
e_l := event_1.UpdateChannel() e_l := event_1.UpdateChannel()
r_l := r.UpdateChannel() r_l := r.UpdateChannel()
(*graph_tester)(t).CheckForNone(e_l) (*graph_tester)(t).CheckForNone(e_l, "Update on event_1 before starting")
(*graph_tester)(t).CheckForNone(r_l) (*graph_tester)(t).CheckForNone(r_l, "Update on r_1 before starting")
if r.Owner() != event_1 { if r.Owner() != event_1 {
t.Fatal("r is not owned by event_1") t.Fatal("r is not owned by event_1")
@ -282,8 +286,8 @@ func TestStartBaseEvent(t * testing.T) {
t.Fatal(err) t.Fatal(err)
} }
// Check that the update channels for the event and resource have updates // Check that the update channels for the event and resource have updates
(*graph_tester)(t).CheckForNil(e_l) (*graph_tester)(t).CheckForValue(e_l, "No update on event_1 after starting")
(*graph_tester)(t).CheckForNil(r_l) (*graph_tester)(t).CheckForValue(r_l, "No update on r_l after starting")
if r.Owner() != nil { if r.Owner() != nil {
t.Fatal("r still owned after event completed") t.Fatal("r still owned after event completed")
@ -342,7 +346,7 @@ func TestStartEventQueue(t * testing.T) {
if err != nil { if err != nil {
t.Fatal("Failed to add e1 to manager") t.Fatal("Failed to add e1 to manager")
} }
(*graph_tester)(t).CheckForNil(rel) (*graph_tester)(t).CheckForValue(rel, "No update on root_event after adding e1")
e2 := NewEvent("1", "", []Resource{res_1}) e2 := NewEvent("1", "", []Resource{res_1})
e2_r := e2.DoneResource() e2_r := e2.DoneResource()
@ -351,7 +355,7 @@ func TestStartEventQueue(t * testing.T) {
if err != nil { if err != nil {
t.Fatal("Failed to add e2 to manager") t.Fatal("Failed to add e2 to manager")
} }
(*graph_tester)(t).CheckForNil(rel) (*graph_tester)(t).CheckForValue(rel, "No update on root_event after adding e2")
e3 := NewEvent("1", "", []Resource{res_2}) e3 := NewEvent("1", "", []Resource{res_2})
e3_r := e3.DoneResource() e3_r := e3.DoneResource()
@ -360,7 +364,7 @@ func TestStartEventQueue(t * testing.T) {
if err != nil { if err != nil {
t.Fatal("Failed to add e3 to manager") t.Fatal("Failed to add e3 to manager")
} }
(*graph_tester)(t).CheckForNil(rel) (*graph_tester)(t).CheckForValue(rel, "No update on root_event after adding e3")
e1_l := e1.UpdateChannel(); e1_l := e1.UpdateChannel();
e2_l := e2.UpdateChannel(); e2_l := e2.UpdateChannel();
@ -387,15 +391,15 @@ func TestStartEventQueue(t * testing.T) {
if e1_r.Owner() != nil { if e1_r.Owner() != nil {
t.Fatal("e1 was not completed") t.Fatal("e1 was not completed")
} }
(*graph_tester)(t).CheckForNil(e1_l) (*graph_tester)(t).CheckForValue(e1_l, "No update on e1 after running")
if e2_r.Owner() != nil { if e2_r.Owner() != nil {
t.Fatal("e2 was not completed") t.Fatal("e2 was not completed")
} }
(*graph_tester)(t).CheckForNil(e2_l) (*graph_tester)(t).CheckForValue(e2_l, "No update on e2 after running")
if e3_r.Owner() != nil { if e3_r.Owner() != nil {
t.Fatal("e3 was not completed") t.Fatal("e3 was not completed")
} }
(*graph_tester)(t).CheckForNil(e3_l) (*graph_tester)(t).CheckForValue(e3_l, "No update on e3 after running")
} }

@ -37,6 +37,7 @@ type Resource interface {
Parents() []Resource Parents() []Resource
Lock(event Event) error Lock(event Event) error
NotifyLocked() error NotifyLocked() error
NotifyUnlocked() error
Unlock(event Event) error Unlock(event Event) error
Owner() Event Owner() Event
Connect(abort chan error) bool Connect(abort chan error) bool
@ -60,6 +61,22 @@ func (resource * BaseResource) Owner() Event {
return resource.lock_holder return resource.lock_holder
} }
func (resource * BaseResource) NotifyUnlocked() error {
err := resource.Update("finalize_unlock")
if err != nil {
return err
}
for _, child := range(resource.children) {
err = child.NotifyUnlocked()
if err != nil {
return err
}
}
return nil
}
func (resource * BaseResource) NotifyLocked() error { func (resource * BaseResource) NotifyLocked() error {
err := resource.Update("finalize_lock") err := resource.Update("finalize_lock")
if err != nil { if err != nil {
@ -73,6 +90,8 @@ func (resource * BaseResource) NotifyLocked() error {
} }
} }
resource.lock_holder.Update("finalize_lock")
return nil return nil
} }

@ -200,15 +200,13 @@ func NewMatch(alliance0 * Alliance, alliance1 * Alliance, arena * Arena) * Match
match.LockDone() match.LockDone()
match.actions["start"] = func() (string, error) { match.actions["start"] = func() (string, error) {
log.Printf("Starting match %s", match.Name()) log.Printf("STARTING_MATCH %s", match.Name())
log.Printf("%s", match.RequiredResources()[2].Owner().Name())
match.control = "none" match.control = "none"
match.state = "scheduled" match.state = "scheduled"
return "wait", nil return "wait", nil
} }
match.actions["queue_autonomous"] = func() (string, error) { match.actions["queue_autonomous"] = func() (string, error) {
log.Printf("queue_autonomous")
match.control = "none" match.control = "none"
match.state = "autonomous_queued" match.state = "autonomous_queued"
match.control_start = time.Now().Add(start_slack) match.control_start = time.Now().Add(start_slack)
@ -216,7 +214,6 @@ func NewMatch(alliance0 * Alliance, alliance1 * Alliance, arena * Arena) * Match
} }
match.actions["start_autonomous"] = func() (string, error) { match.actions["start_autonomous"] = func() (string, error) {
log.Printf("start_autonomous")
match.control = "autonomous" match.control = "autonomous"
match.state = "autonomous_running" match.state = "autonomous_running"
return "wait", nil return "wait", nil