grafana/xk6

WebSocket assignment to entry in nil map

Closed this issue · 2 comments

Greetings!

I'm trying to use xk6 with WebSocket:

package consumer

import (
	"context"
	"fmt"

	"github.com/dop251/goja"
	"go.k6.io/k6/js/common"
	"go.k6.io/k6/js/modules"
	"go.k6.io/k6/js/modules/k6/ws"
)

func init() {
	modules.Register("k6/x/graphql", new(GraphQL))
}

type GraphQL struct{}

type Client struct {
	rt     *goja.Runtime
	socket ws.Socket
	token  string
	query  string
}

func (c *GraphQL) XClient(ctxPtr *context.Context, socket ws.Socket, token string, query string) interface{} {
	rt := common.GetRuntime(*ctxPtr)
	return common.Bind(
		rt,
		&Client{
			rt:     rt,
			socket: socket,
			token:  token,
			query:  query,
		},
		ctxPtr,
	)
}

func (c *Client) Start() {
	c.socket.On("open", c.rt.ToValue(func() {
		c.socket.Send(fmt.Sprintf("{\"type\":\"connection_init\",\"payload\":{\"authToken\":\"%s\"}}", c.token))
	}))
}
export default function(token) {
    const params = {
        headers: {
            "sec-websocket-protocol": "graphql-transport-ws"
        }
    };

    const res = ws.connect(WS_URL, params, function(socket) {
        const client = new GraphQL.Client(socket, token, QUERY);
        client.start();
    });
    check(res, {
        "WebSocket /graphql status is 101": (r) => r && r.status === 101
    });
}

And getting errors like these:

ERRO[0002] panic: assignment to entry in nil map
goroutine 268 [running]:
runtime/debug.Stack(0xc005f014b0, 0xc005f014d0, 0xc005f014a0)
        runtime/debug/stack.go:24 +0x9f
go.k6.io/k6/js.(*VU).runFn.func1(0xc0008a5d60, 0xc005f03c38)
        go.k6.io/k6@v0.33.0/js/runner.go:737 +0x1e5
panic(0x10dcc00, 0x147b070)
        runtime/panic.go:965 +0x1b9
github.com/dop251/goja.AssertFunction.func1.1(0xc005f03b30)
        github.com/dop251/goja@v0.0.0-20210427212725-462d53687b0d/runtime.go:2090 +0x95
panic(0x10dcc00, 0x147b070)
        runtime/panic.go:965 +0x1b9
github.com/dop251/goja.(*vm).try.func1(0xc0022eca00, 0x0, 0xc005f039e0, 0x0, 0x0, 0x0, 0xc005f03a78)
        github.com/dop251/goja@v0.0.0-20210427212725-462d53687b0d/vm.go:505 +0xc1d
panic(0x10dcc00, 0x147b070)
        runtime/panic.go:965 +0x1b9
github.com/dop251/goja.AssertFunction.func1.1(0xc005f02b78)
        github.com/dop251/goja@v0.0.0-20210427212725-462d53687b0d/runtime.go:2090 +0x95
panic(0x10dcc00, 0x147b070)
        runtime/panic.go:965 +0x1b9
github.com/dop251/goja.(*vm).try.func1(0xc0022eca00, 0x2, 0xc005f02a28, 0x8, 0x0, 0x0, 0xc005f02ac0)
        github.com/dop251/goja@v0.0.0-20210427212725-462d53687b0d/vm.go:505 +0xc1d
panic(0x10dcc00, 0x147b070)
        runtime/panic.go:965 +0x1b9
go.k6.io/k6/js/modules/k6/ws.(*Socket).On(...)
        go.k6.io/k6@v0.33.0/js/modules/k6/ws/ws.go:329
<EXT>.(*Client).Start(0xc007ceed80)
        <EXT>@v0.0.0-00010101000000-000000000000/consumer.go:41 +0xd9
reflect.Value.call(0x1071300, 0xc001939940, 0x13, 0x126180a, 0x4, 0x1de9058, 0x0, 0x0, 0xc005f02500, 0x44fcec, ...)
        reflect/value.go:476 +0x8e7
reflect.Value.Call(0x1071300, 0xc001939940, 0x13, 0x1de9058, 0x0, 0x0, 0xc007e47440, 0x0, 0xc005f026d0)
        reflect/value.go:337 +0xb9
github.com/dop251/goja.(*Runtime).wrapReflectFunc.func1(0x14b7cf8, 0xc0084525a0, 0xc005861750, 0x0, 0xb, 0x1071300, 0xc001939940)
        github.com/dop251/goja@v0.0.0-20210427212725-462d53687b0d/runtime.go:1701 +0x3be
github.com/dop251/goja.(*vm)._nativeCall(0xc0022eca00, 0xc007e47440, 0x0)
        github.com/dop251/goja@v0.0.0-20210427212725-462d53687b0d/vm.go:2357 +0x266
github.com/dop251/goja.call.exec(0x0, 0xc0022eca00)
        github.com/dop251/goja@v0.0.0-20210427212725-462d53687b0d/vm.go:2329 +0x776
github.com/dop251/goja.(*vm).run(0xc0022eca00)
        github.com/dop251/goja@v0.0.0-20210427212725-462d53687b0d/vm.go:395 +0x94
github.com/dop251/goja.(*funcObject).call(0xc002f87ad0, 0x14b8548, 0x1de8ca0, 0xc002463340, 0x1, 0x1, 0x0, 0x0, 0x4de009, 0x11b59e0)
        github.com/dop251/goja@v0.0.0-20210427212725-462d53687b0d/func.go:161 +0x225
github.com/dop251/goja.(*funcObject).Call(...)
        github.com/dop251/goja@v0.0.0-20210427212725-462d53687b0d/func.go:129
github.com/dop251/goja.AssertFunction.func1.2()
        github.com/dop251/goja@v0.0.0-20210427212725-462d53687b0d/runtime.go:2095 +0x96
github.com/dop251/goja.(*vm).try(0xc0022eca00, 0xc005f02ae0, 0x0)
        github.com/dop251/goja@v0.0.0-20210427212725-462d53687b0d/vm.go:511 +0x188
github.com/dop251/goja.AssertFunction.func1(0x14b8548, 0x1de8ca0, 0xc002463340, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0)
        github.com/dop251/goja@v0.0.0-20210427212725-462d53687b0d/runtime.go:2094 +0x10b
go.k6.io/k6/js/modules/k6/ws.(*WS).Connect(0x1de9058, 0x14a6768, 0xc0019d8330, 0xc0005019c0, 0x1b, 0xc0018c8a60, 0x2, 0x2, 0x0, 0x0, ...)
        go.k6.io/k6@v0.33.0/js/modules/k6/ws/ws.go:219 +0xb33
reflect.Value.call(0x10beb40, 0x1de9058, 0x213, 0x1267225, 0x9, 0xc0063a9590, 0x3, 0x3, 0xb, 0x11a6ee0, ...)
        reflect/value.go:476 +0x8e7
reflect.Value.CallSlice(0x10beb40, 0x1de9058, 0x213, 0xc0063a9590, 0x3, 0x3, 0x194, 0x1, 0x2)
        reflect/value.go:350 +0xb9
go.k6.io/k6/js/common.Bind.func1(0x14b7cf8, 0xc004242ed0, 0xc0058616d0, 0x3, 0x13, 0x40, 0xc001b6f6c0)
        go.k6.io/k6@v0.33.0/js/common/bridge.go:241 +0x749
github.com/dop251/goja.(*vm)._nativeCall(0xc0022eca00, 0xc008146900, 0x3)
        github.com/dop251/goja@v0.0.0-20210427212725-462d53687b0d/vm.go:2357 +0x266
github.com/dop251/goja.call.exec(0x3, 0xc0022eca00)
        github.com/dop251/goja@v0.0.0-20210427212725-462d53687b0d/vm.go:2329 +0x776
github.com/dop251/goja.(*vm).run(0xc0022eca00)
        github.com/dop251/goja@v0.0.0-20210427212725-462d53687b0d/vm.go:395 +0x94
github.com/dop251/goja.(*funcObject).call(0xc004205520, 0x14b8548, 0x1de8ca0, 0xc00107f590, 0x1, 0x1, 0x0, 0x0, 0x442500, 0xc00517e180)
        github.com/dop251/goja@v0.0.0-20210427212725-462d53687b0d/func.go:161 +0x225
github.com/dop251/goja.(*funcObject).Call(...)
        github.com/dop251/goja@v0.0.0-20210427212725-462d53687b0d/func.go:129
github.com/dop251/goja.AssertFunction.func1.2()
        github.com/dop251/goja@v0.0.0-20210427212725-462d53687b0d/runtime.go:2095 +0x96
github.com/dop251/goja.(*vm).try(0xc0022eca00, 0xc005f03a98, 0x0)
        github.com/dop251/goja@v0.0.0-20210427212725-462d53687b0d/vm.go:511 +0x188
github.com/dop251/goja.AssertFunction.func1(0x14b8548, 0x1de8ca0, 0xc00107f590, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0)
        github.com/dop251/goja@v0.0.0-20210427212725-462d53687b0d/runtime.go:2094 +0x10b
go.k6.io/k6/js.(*VU).runFn(0xc0008a5d60, 0x14a6768, 0xc0019d8330, 0x1082001, 0xc00193ac18, 0xc00107f590, 0x1, 0x1, 0x0, 0x0, ...)
        go.k6.io/k6@v0.33.0/js/runner.go:742 +0x154
go.k6.io/k6/js.(*ActiveVU).RunOnce(0xc001901c00, 0x0, 0x0)
        go.k6.io/k6@v0.33.0/js/runner.go:693 +0x414
go.k6.io/k6/lib/executor.getIterationRunner.func1(0x14a66c0, 0xc0050312c0, 0x1490b60, 0xc001901c00, 0x1)
        go.k6.io/k6@v0.33.0/lib/executor/helpers.go:88 +0x5e
go.k6.io/k6/lib/executor.(*vuHandle).runLoopsIfPossible(0xc004efb320, 0xc001e0cc78)
        go.k6.io/k6@v0.33.0/lib/executor/vu_handle.go:225 +0x555
created by go.k6.io/k6/lib/executor.RampingVUs.Run
        go.k6.io/k6@v0.33.0/lib/executor/ramping_vus.go:579 +0xde6

Goja stack:
native 
ERRO[0002] a panic occurred in VU code but was caught: assignment to entry in nil map  executor=ramping-vus scenario=default

What am I doing wrong?

You need to be taking a pointer to ws.Socket in XClient and then move that around instead of a non-pointer value.

I think this is a problem with goja more than with k6/xk6, but will need more time to actually investigate it as it seems that if it sees a struct and it has a pointer to the same struct the ExportTo doesn't actually just dereference the pointer but instead tries to copy exported fields, which in the case of ws.Socket copies nothing. But I need more tests to confirm this ;)

ou need to be taking a pointer to ws.Socket in XClient and then move that around instead of a non-pointer value.

Thanks! Changing ws.Socket to *ws.Socket solved the problem!