Skip to content

Commit 77598ca

Browse files
authored
Merge pull request #1643 from lebauce/workflow-tests
tests: add tests for workflows
2 parents 9bd1615 + ad108d8 commit 77598ca

File tree

8 files changed

+272
-40
lines changed

8 files changed

+272
-40
lines changed

cmd/client/workflow.go

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,11 @@
1818
package client
1919

2020
import (
21-
"fmt"
2221
"io/ioutil"
2322
"os"
2423

2524
"gopkg.in/yaml.v2"
2625

27-
"github.com/robertkrimen/otto"
28-
2926
"github.com/skydive-project/skydive/api/client"
3027
"github.com/skydive-project/skydive/api/types"
3128
"github.com/skydive-project/skydive/js"
@@ -173,40 +170,16 @@ var WorkflowCall = &cobra.Command{
173170
runtime.Start()
174171
runtime.RegisterAPIClient(client)
175172

176-
result, err := runtime.Exec("(" + workflow.Source + ")")
177-
if err != nil {
178-
exitOnError(fmt.Errorf("Error while compile workflow %s: %s", workflow.Source, result.String()))
179-
}
180-
181173
params := make([]interface{}, len(args)-1)
182174
for i, arg := range args[1:] {
183175
params[i] = arg
184176
}
185177

186-
result, err = result.Call(result, params...)
178+
result, err := runtime.ExecPromise(workflow.Source, params...)
187179
if err != nil {
188-
exitOnError(fmt.Errorf("Error while executing workflow: %s", result.String()))
189-
}
190-
191-
if !result.IsObject() {
192-
exitOnError(fmt.Errorf("Workflow is expected to return a promise, returned %s", result.Class()))
180+
exitOnError(err)
193181
}
194182

195-
done := make(chan otto.Value)
196-
promise := result.Object()
197-
198-
finally, err := runtime.ToValue(func(call otto.FunctionCall) otto.Value {
199-
result := call.Argument(0)
200-
done <- result
201-
return result
202-
})
203-
204-
result, _ = promise.Call("then", finally)
205-
promise = result.Object()
206-
promise.Call("catch", finally)
207-
208-
result = <-done
209-
210183
runtime.Set("result", result)
211184
runtime.Exec("console.log(JSON.stringify(result))")
212185
},

graffiti/graph/graph.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,14 +103,14 @@ type graphElement struct {
103103

104104
// Node of the graph
105105
type Node struct {
106-
graphElement
106+
graphElement `mapstructure:",squash"`
107107
}
108108

109109
// Edge of the graph linked by a parent and a child
110110
type Edge struct {
111-
graphElement
112-
Parent Identifier
113-
Child Identifier
111+
graphElement `mapstructure:",squash"`
112+
Parent Identifier
113+
Child Identifier
114114
}
115115

116116
// Graph errors

js/otto.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,6 @@ function require(m) {
3131
return {}
3232
}
3333

34+
var api = require("./api");
35+
3436
Promise.prototype.finally = Promise.prototype.done

js/runtime.go

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"math/rand"
2828
"os"
2929
"strings"
30+
"sync"
3031
"time"
3132

3233
"github.com/robertkrimen/otto"
@@ -55,6 +56,7 @@ type jsTimer struct {
5556
// Runtime is a Skydive JavaScript runtime environment
5657
type Runtime struct {
5758
*otto.Otto
59+
sync.Mutex
5860
evalQueue chan *evalReq
5961
stopEventLoop chan bool
6062
closed chan struct{}
@@ -386,19 +388,70 @@ func (r *Runtime) Do(fn func(*otto.Otto)) {
386388
<-done
387389
}
388390

389-
// Exec executes some JavaScript code
391+
// Exec queues the execution of some JavaScript code
390392
func (r *Runtime) Exec(code string) (v otto.Value, err error) {
391393
r.Do(func(vm *otto.Otto) { v, err = vm.Run(code) })
392394
return v, err
393395
}
394396

397+
// ExecFunction queues a CallFunction method
398+
func (r *Runtime) ExecFunction(source string, params ...interface{}) (v otto.Value, err error) {
399+
r.Do(func(vm *otto.Otto) { v, err = r.CallFunction(source, params...) })
400+
return v, err
401+
}
402+
403+
// ExecPromise executes a promise and return its result
404+
func (r *Runtime) ExecPromise(source string, params ...interface{}) (v otto.Value, err error) {
405+
var done chan otto.Value
406+
r.Do(func(vm *otto.Otto) { done, err = r.CallPromise(source, params...) })
407+
v = <-done
408+
return v, err
409+
}
410+
411+
// CallFunction takes the source of a function and evaluate it with the specifed parameters
412+
func (r *Runtime) CallFunction(source string, params ...interface{}) (otto.Value, error) {
413+
result, err := r.Run("(" + source + ")")
414+
if err != nil {
415+
return otto.UndefinedValue(), fmt.Errorf("Error while compile source %s: %s", source, result.String())
416+
}
417+
418+
return result.Call(result, params...)
419+
}
420+
421+
// CallPromise takes the source of a promise and evaluate it with the specifed parameters
422+
func (r *Runtime) CallPromise(source string, params ...interface{}) (chan otto.Value, error) {
423+
result, err := r.CallFunction(source, params...)
424+
if err != nil {
425+
return nil, fmt.Errorf("Error while executing function: %s", err)
426+
}
427+
428+
if !result.IsObject() {
429+
return nil, fmt.Errorf("Workflow is expected to return a promise, returned %s", result.Class())
430+
}
431+
432+
done := make(chan otto.Value)
433+
promise := result.Object()
434+
finally, err := r.ToValue(func(call otto.FunctionCall) otto.Value {
435+
result = call.Argument(0)
436+
done <- result
437+
return result
438+
})
439+
440+
result, _ = promise.Call("then", finally)
441+
promise = result.Object()
442+
promise.Call("catch", finally)
443+
444+
return done, nil
445+
}
446+
395447
// Start the runtime evaluation loop
396448
func (r *Runtime) Start() {
397449
go r.runEventLoop()
398450
}
399451

400452
// Stop the runtime evaluation loop
401453
func (r *Runtime) Stop() {
454+
r.stopEventLoop <- true
402455
}
403456

404457
// NewRuntime returns a new JavaScript runtime environment

statics/workflows/flow-matrix.yaml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ parameters:
2020
type: boolean
2121
source: |
2222
function FlowMatrix(useFlows, format, debug) {
23+
format = format || "graph"
24+
2325
var G = client.gremlin.G()
2426
var at;
2527
var listenPorts = []
@@ -30,8 +32,8 @@ source: |
3032
var hostAddresses = {}
3133
3234
var isLoopback = function(addr) {
33-
return addr.startsWith("127.") ||
34-
addr.startsWith("::1/")
35+
return addr.indexOf("127.") == 0 ||
36+
addr.indexOf("::1/") == 0
3537
}
3638
3739
var isListenSocket = function(socket) {
@@ -251,7 +253,7 @@ source: |
251253
}
252254
}
253255
254-
var buildGraph = function() {
256+
var outputGraph = function() {
255257
log("Matrix", matrix)
256258
257259
var endpoints = buildEndpoints()
@@ -311,7 +313,7 @@ source: |
311313
case "dot":
312314
return outputDot()
313315
case "graph":
314-
return buildGraph()
316+
return outputGraph()
315317
}
316318
}
317319

tests/tests.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ agent:
8484
- lxd
8585
- lldp
8686
- runc
87+
- socketinfo
8788
{{.OpencontrailProbe}}
8889
netlink:
8990
metrics_update: 5

0 commit comments

Comments
 (0)