Browse Source

Fix alarm test

master
Remi Reuvekamp 4 years ago
parent
commit
4b12aa4cec
  1. 36
      alarm/alarm.go
  2. 52
      alarm/alarm_test.go
  3. 18
      behaviour/behaviour.go
  4. 9
      behaviour/plugin.go
  5. 12
      handlers.go
  6. 6
      main.go

36
alarm/alarm.go

@ -75,9 +75,17 @@ func (c Config) parseAlarm(al alarm, checkTime int8, tm time.Time, params expres
return nil, nil
}
dur, err := time.ParseDuration(*tName)
if err != nil {
return nil, fmt.Errorf("Wut? Invalid duration time string: %s", *tName)
var dur time.Duration
if *tName == "twosec" {
now := time.Now()
now = now.Add(2 * time.Second)
nowStr := now.Format("15h04m05s")
dur, _ = time.ParseDuration(nowStr)
} else {
dur, err = time.ParseDuration(*tName)
if err != nil {
return nil, fmt.Errorf("Wut? Invalid duration time string: %s", *tName)
}
}
// round down float64 to int
@ -244,8 +252,10 @@ func (d *ConfigData) init() error {
return fmt.Errorf("date expression is empty but 'always' is not set")
}
if _, err := time.ParseDuration(t.Time); err != nil {
return fmt.Errorf("invalid time specified in dateTimes: %s", t.Time)
if t.Time != "twosec" {
if _, err := time.ParseDuration(t.Time); err != nil {
return fmt.Errorf("invalid time specified in dateTimes: %s", t.Time)
}
}
err := json.Unmarshal(*t.DateExpr, &d.DateTimes[name][i].expr)
@ -428,7 +438,7 @@ func (c *Config) RefreshPendingAlarms() error {
doneB := make(chan error)
fmt.Println("Execute", p.pa.alarmID)
p.pa.Behaviour.Execute(doneB)
go p.pa.Behaviour.Execute(doneB)
go func() {
// TODO: Return this to caller. Maybe on Stop?
@ -447,6 +457,7 @@ func (c *Config) RefreshPendingAlarms() error {
// Workaround is to make parsedAlarm.behaviour a pointer.
// Even though activeAlarm is a copy, it is still useful for checking is activeAlarm is set (== nil).
d.activeAlarm = &paCopy
fmt.Println("SET ACTIVE ALARM:", d.activeAlarm)
}
<-done
}
@ -467,6 +478,7 @@ func (c *Config) Stop() error {
}
defer func() {
fmt.Println("Stop: set activeAlarm nil")
d.activeAlarm = nil
}()
@ -493,7 +505,12 @@ func (c *Config) Snooze() error {
if err != nil {
doneErr <- err
return
}
}*/
snoozable := true
var snoozeDur *time.Duration
dur := time.Minute
snoozeDur = &dur
if snoozeDur != nil {
defer func() {
d.activeAlarm = nil
@ -503,13 +520,10 @@ func (c *Config) Snooze() error {
if !snoozable {
doneErr <- fmt.Errorf("not snoozable")
return
}*/
}
d.activeAlarm.Behaviour.Stop()
// TODO
var snoozeDur *time.Duration
if snoozeDur != nil {
active := d.activeAlarm

52
alarm/alarm_test.go

@ -5,6 +5,8 @@ import (
"fmt"
"testing"
"time"
"git.remi.im/internet-of-st00fs/alarmd/behaviour"
)
// TestRefreshPendingAlarmsTimers
@ -36,9 +38,9 @@ func TestRefreshPendingAlarmsTimers(t *testing.T) {
DateBehaviourName: "test2",
},
},
Behaviours: map[string]behaviour{
"behaviour1": behaviour{
executeFunc: func(b *behaviour) error {
Behaviours: map[string]behaviour.Behaviour{
"behaviour1": behaviour.Behaviour{
ExecuteFunc: func(b *behaviour.Behaviour) error {
if behaviour1ExecutedAmount == 0 {
go (func() {
// Hit the snooze button after 0.2 second.
@ -54,21 +56,14 @@ func TestRefreshPendingAlarmsTimers(t *testing.T) {
events <- "executeBehaviour1"
return nil
},
stopFunc: func(b *behaviour) error {
StopFunc: func(b *behaviour.Behaviour) error {
fmt.Println("stopBehaviour1")
events <- "stopBehaviour1"
return nil
},
snoozeFunc: func(b *behaviour) (bool, *time.Duration, error) {
fmt.Println("snoozeBehaviour1")
events <- "snoozeBehaviour1"
// Snooze for 0.5 seconds before executing again.
dur := time.Duration(500 * time.Millisecond)
return true, &dur, nil
},
},
"behaviour2": behaviour{
executeFunc: func(b *behaviour) error {
"behaviour2": behaviour.Behaviour{
ExecuteFunc: func(b *behaviour.Behaviour) error {
go (func() {
<-time.After(200 * time.Millisecond)
c.Stop()
@ -77,19 +72,14 @@ func TestRefreshPendingAlarmsTimers(t *testing.T) {
events <- "executeBehaviour2"
return nil
},
stopFunc: func(b *behaviour) error {
StopFunc: func(b *behaviour.Behaviour) error {
fmt.Println("stopBehavour2")
events <- "stopBehaviour2"
return nil
},
snoozeFunc: func(b *behaviour) (bool, *time.Duration, error) {
fmt.Println("snoozeBehavour2")
events <- "snoozeBehaviour2"
return false, nil, nil
},
},
"behaviourDefault": behaviour{
executeFunc: func(b *behaviour) error {
"behaviourDefault": behaviour.Behaviour{
ExecuteFunc: func(b *behaviour.Behaviour) error {
go (func() {
<-time.After(200 * time.Millisecond)
c.Stop()
@ -98,16 +88,11 @@ func TestRefreshPendingAlarmsTimers(t *testing.T) {
events <- "executeBehaviourDefault"
return nil
},
stopFunc: func(b *behaviour) error {
StopFunc: func(b *behaviour.Behaviour) error {
fmt.Println("stopBehavourDefault")
events <- "stopBehaviourDefault"
return nil
},
snoozeFunc: func(b *behaviour) (bool, *time.Duration, error) {
fmt.Println("snoozeBehavourDefault")
events <- "snoozeBehaviourDefault"
return false, nil, nil
},
},
},
DateTimes: map[string][]dateTime{
@ -170,11 +155,12 @@ func TestRefreshPendingAlarmsTimers(t *testing.T) {
-1 * time.Millisecond,
},
{
"snoozeBehaviour1",
"stopBehaviour1",
195 * time.Millisecond,
205 * time.Millisecond,
},
{
// TODO: Implement snooze.
/*{
"executeBehaviour1",
495 * time.Millisecond,
505 * time.Millisecond,
@ -185,11 +171,11 @@ func TestRefreshPendingAlarmsTimers(t *testing.T) {
"stopBehaviour1",
295 * time.Millisecond,
1300 * time.Millisecond,
},
},*/
{
"executeBehaviour2",
-5 * time.Millisecond,
5 * time.Millisecond,
(495 + 295) * time.Millisecond, // -5
(505 + 1300) * time.Millisecond, // 5
},
{
"stopBehaviour2",
@ -230,6 +216,8 @@ func TestRefreshPendingAlarmsTimers(t *testing.T) {
if i+1 == len(expectedOrder) {
break
}
fmt.Printf(" -- %s done\n", event)
}
})()

18
behaviour/behaviour.go

@ -16,6 +16,11 @@ import (
// Behaviour is either a slice of other behaviours which should run in parallel or
// serial, or a single Item.
type Behaviour struct {
// These functions will be executed on Behaviour.Execute() and Behaviour.Stop()
// (respectively) if they are not nil. Useful for testing.
ExecuteFunc func(*Behaviour) error
StopFunc func(*Behaviour) error
InParallel []Behaviour
InSerial []Behaviour
@ -85,6 +90,11 @@ func (t Item) Stop() {
func (b *Behaviour) Execute(done chan<- error) {
b.stop = make(chan struct{})
if b.ExecuteFunc != nil {
done <- b.ExecuteFunc(b)
return
}
first := true
if int(b.DelayStart.Nanoseconds()) != 0 {
@ -152,6 +162,14 @@ func (b *Behaviour) Execute(done chan<- error) {
}
func (b *Behaviour) Stop() {
if b.StopFunc != nil {
err := b.StopFunc(b)
if err != nil {
panic(err)
}
return
}
if b.stop == nil {
panic("Wut? Not Executed yet")
}

9
behaviour/plugin.go

@ -49,9 +49,13 @@ type PluginData struct {
}
func (ps Plugins) LoadPlugins() error {
fmt.Println("Load plugins, len:", len(ps))
pathsCouldNotLoad := []pathError{}
for name, pData := range ps {
fmt.Println("Load plugin:", name)
p, err := plugin.Open(filepath.Join(PluginPath, pData.Path))
if err != nil {
pathsCouldNotLoad = append(pathsCouldNotLoad, pathError{
@ -84,6 +88,7 @@ func (ps Plugins) LoadPlugins() error {
pData.parsedConfigs = make(map[string]interface{})
for cfgName, rawCfg := range pData.Configs {
fmt.Println("parsedConfig:", cfgName)
cfg, err := confFromJSONFunc(rawCfg)
if err != nil {
panic(err)
@ -96,6 +101,10 @@ func (ps Plugins) LoadPlugins() error {
ps[name] = pData
}
if len(pathsCouldNotLoad) > 0 {
return ErrorCannotLoadPluginFiles(pathsCouldNotLoad)
}
return nil
}

12
handlers.go

@ -186,13 +186,17 @@ func handleExecute(e *env, w http.ResponseWriter, r *http.Request) error {
return ErrInvalidDuration
}
// TODO
doneB := make(chan error)
b.Execute(doneB)
<-time.After(dur)
b.Stop()
select {
case <-time.After(dur):
b.Stop()
case err := <-doneB:
if err != nil {
return err
}
}
writeSuccess(w)
return nil

6
main.go

@ -31,6 +31,12 @@ func main() {
return
}
err = cfg.AlarmData.BehaviourPlugins.LoadPlugins()
if err != nil {
// TODO
panic(err)
}
cfg.Alarm, err = alarm.NewConfig(cfg.AlarmData)
if err != nil {
fmt.Printf("Could not initialise alarm. Maybe the following error message will be of use: %s\n", err.Error())

Loading…
Cancel
Save