Skip to content
This repository was archived by the owner on Apr 24, 2025. It is now read-only.

Commit 4953c64

Browse files
authored
Merge pull request #72 from tetratelabs/tinyfix
internal fix of proxytest / enhance docs
2 parents 0e8ae5f + 6a89e4b commit 4953c64

File tree

9 files changed

+113
-92
lines changed

9 files changed

+113
-92
lines changed

Makefile

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@
22

33
ISTIO_VERSION ?= 1.7.2
44

5-
.PHONY: help build.example build.examples lint test test.sdk test.e2e
6-
help:
7-
grep -E '^[a-z0-9A-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
5+
.PHONY: build.example build.examples lint test test.sdk test.e2e
86

97
build.example:
10-
tinygo build -o ./examples/${name}/main.go.wasm -target=wasi -wasm-abi=generic ./examples/${name}/main.go
8+
tinygo build -o ./examples/${name}/main.go.wasm -scheduler=none -target=wasi -wasm-abi=generic ./examples/${name}/main.go
119

1210
build.examples:
1311
find ./examples -type f -name "main.go" | xargs -Ip tinygo build -o p.wasm -target=wasi -wasm-abi=generic p

README.md

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,25 +84,31 @@ make test # run local tests without running envoy processes
8484
make test.e2e # run e2e tests
8585
```
8686

87-
## compiler limitations and considerations
87+
## limitations and considerations
8888

8989
- Some of existing libraries are not available (importable but runtime panic / non-importable)
90-
- There are two reasons for this:
90+
- There are several reasons for this:
9191
1. TinyGo's WASI target does not support some of syscall: For example, we cannot import `crypto/rand` package.
9292
2. TinyGo does not implement all of reflect package([examples](https://github.com/tinygo-org/tinygo/blob/v0.14.1/src/reflect/value.go#L299-L305)).
93-
- These issues will be mitigated as the TinyGo improves.
94-
- There's performance overhead in using Go/TinyGo due to GC
95-
- runtime.GC() is called whenever the heap runs out (see [1](https://tinygo.org/lang-support/#garbage-collection),
93+
3. [proxy-wasm-cpp-host](https://github.com/proxy-wasm/proxy-wasm-cpp-host) has not supported some of WASI APIs yet
94+
(see the [supported functions](https://github.com/proxy-wasm/proxy-wasm-cpp-host/blob/master/include/proxy-wasm/exports.h#L134-L147)).
95+
For example, `clock_time_get` is not implemented, and therefore we cannot use `time.Now` function.
96+
- These issues will be mitigated as TinyGo and proxy-wasm-cpp-host evolve.
97+
- There's performance overhead of using Go/TinyGo due to GC
98+
- `runtime.GC` is called whenever the heap runs out (see [1](https://tinygo.org/lang-support/#garbage-collection),
9699
[2](https://github.com/tinygo-org/tinygo/blob/v0.14.1/src/runtime/gc_conservative.go#L218-L239)).
97100
- TinyGo allows us to disable GC, but we cannot do that since we need to use maps (implicitly causes allocation)
98-
for saving the plugin's [state](https://github.com/tetratelabs/proxy-wasm-go-sdk/blob/master/proxywasm/vmstate.go#L17-L22).
101+
for saving the plugin's [state](https://github.com/tetratelabs/proxy-wasm-go-sdk/blob/cf6ad74ed58b284d3d8ceeb8c5dba2280d5b1007/proxywasm/vmstate.go#L41-L46).
99102
- Theoretically, we can implement our own GC algorithms tailored for proxy-wasm through `alloc(uintptr)` [interface](https://github.com/tinygo-org/tinygo/blob/v0.14.1/src/runtime/gc_none.go#L13)
100103
with `-gc=none` option. This is the future TODO.
101104
- `recover` is [not implemented](https://github.com/tinygo-org/tinygo/issues/891) in TinyGo, and there's no way to prevent the WASM virtual machine from aborting.
102-
- Be careful about using Goroutine
105+
- Goroutine support
103106
- In Tinygo, Goroutine is implmeneted through LLVM's coroutine (see [this blog post](https://aykevl.nl/2019/02/tinygo-goroutines)).
104-
- Make every goroutine exit as soon as possible, otherwise it will block the proxy's worker thread. That is too bad for processing realtime network requests.
105-
- We strongly recommend that you implement the `OnTick` function for any asynchronous task instead of using Goroutine so we do not block requests.
107+
- In Envoy, WASM modules are run in the event driven manner, and therefore the "scheduler" is not executed once the main function exits.
108+
That means you cannot have the expected behavior of Goroutine as in ordinary host environments.
109+
- The question "How to deal with Goroutine in a thread local WASM VM executed in the event drive manner" has yet to be answered.
110+
- We strongly recommend that you implement the `OnTick` function for any asynchronous task instead of using Goroutine.
111+
- The scheduler can be disabled with `-scheduler=none` option of TinyGo.
106112

107113
## references
108114

examples/helloworld/main_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package main
33
import (
44
"strings"
55
"testing"
6-
"time"
76

87
"github.com/stretchr/testify/require"
98

@@ -21,7 +20,8 @@ func TestHelloWorld_OnTick(t *testing.T) {
2120

2221
host.StartVM() // call OnVMStart
2322

24-
time.Sleep(time.Duration(tickMilliseconds) * 4 * time.Millisecond)
23+
assert.Equal(t, tickMilliseconds, host.GetTickPeriod())
24+
host.Tick() // call OnTick
2525

2626
logs := host.GetLogs(types.LogLevelInfo)
2727
require.Greater(t, len(logs), 0)

examples/shared_queue/main_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ package main
1717
import (
1818
"fmt"
1919
"testing"
20-
"time"
2120

2221
"github.com/stretchr/testify/assert"
2322
"github.com/stretchr/testify/require"
@@ -42,9 +41,12 @@ func TestQueue(t *testing.T) {
4241

4342
contextID := host.HttpFilterInitContext()
4443
host.HttpFilterPutRequestHeaders(contextID, nil) // call enqueue
44+
4545
assert.Equal(t, 4, host.GetQueueSize(queueID))
4646

47-
time.Sleep(time.Duration(tickMilliseconds*5) * time.Millisecond)
47+
for i := 0; i < 4; i++ {
48+
host.Tick()
49+
}
4850

4951
logs = host.GetLogs(types.LogLevelInfo)
5052
require.Greater(t, len(logs), 5)

proxytest/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ This framework simulates the expected behavior of Envoyproxy, and you can test y
1010
For detail, see `examples/*/main_test.go`.
1111

1212

13-
Note that we have not covered ll the functionality, and the API is very likely to change in the future.
13+
Note that we have not covered all the functionality, and the API is very likely to change in the future.

proxytest/http.go

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func newHttpHostEmulator() *httpHostEmulator {
4747
return host
4848
}
4949

50-
// impl host rawhostcall.ProxyWASMHost: delegated from hostEmulator
50+
// impl rawhostcall.ProxyWASMHost: delegated from hostEmulator
5151
func (h *httpHostEmulator) httpHostEmulatorProxyGetBufferBytes(bt types.BufferType, start int, maxSize int,
5252
returnBufferData **byte, returnBufferSize *int) types.Status {
5353
active := proxywasm.VMStateGetActiveContextID()
@@ -76,7 +76,7 @@ func (h *httpHostEmulator) httpHostEmulatorProxyGetBufferBytes(bt types.BufferTy
7676
return types.StatusOK
7777
}
7878

79-
// impl host rawhostcall.ProxyWASMHost: delegated from hostEmulator
79+
// impl rawhostcall.ProxyWASMHost: delegated from hostEmulator
8080
func (h *httpHostEmulator) httpHostEmulatorProxyGetHeaderMapValue(mapType types.MapType, keyData *byte,
8181
keySize int, returnValueData **byte, returnValueSize *int) types.Status {
8282
key := proxywasm.RawBytePtrToString(keyData, keySize)
@@ -109,7 +109,7 @@ func (h *httpHostEmulator) httpHostEmulatorProxyGetHeaderMapValue(mapType types.
109109
return types.StatusNotFound
110110
}
111111

112-
// impl host rawhostcall.ProxyWASMHost
112+
// impl rawhostcall.ProxyWASMHost
113113
func (h *httpHostEmulator) ProxyAddHeaderMapValue(mapType types.MapType, keyData *byte,
114114
keySize int, valueData *byte, valueSize int) types.Status {
115115

@@ -145,7 +145,7 @@ func addMapValue(base [][2]string, key, value string) [][2]string {
145145
return append(base, [2]string{key, value})
146146
}
147147

148-
// impl host rawhostcall.ProxyWASMHost
148+
// impl rawhostcall.ProxyWASMHost
149149
func (h *httpHostEmulator) ProxyReplaceHeaderMapValue(mapType types.MapType, keyData *byte,
150150
keySize int, valueData *byte, valueSize int) types.Status {
151151
key := proxywasm.RawBytePtrToString(keyData, keySize)
@@ -168,7 +168,7 @@ func (h *httpHostEmulator) ProxyReplaceHeaderMapValue(mapType types.MapType, key
168168
return types.StatusOK
169169
}
170170

171-
// impl host rawhostcall.ProxyWASMHost
171+
// impl rawhostcall.ProxyWASMHost
172172
func replaceMapValue(base [][2]string, key, value string) [][2]string {
173173
for i, h := range base {
174174
if h[0] == key {
@@ -180,7 +180,7 @@ func replaceMapValue(base [][2]string, key, value string) [][2]string {
180180
return append(base, [2]string{key, value})
181181
}
182182

183-
// impl host rawhostcall.ProxyWASMHost
183+
// impl rawhostcall.ProxyWASMHost
184184
func (h *httpHostEmulator) ProxyRemoveHeaderMapValue(mapType types.MapType, keyData *byte, keySize int) types.Status {
185185
key := proxywasm.RawBytePtrToString(keyData, keySize)
186186
active := proxywasm.VMStateGetActiveContextID()
@@ -214,7 +214,7 @@ func removeHeaderMapValue(base [][2]string, key string) [][2]string {
214214
return base
215215
}
216216

217-
// impl host rawhostcall.ProxyWASMHost: delegated from hostEmulator
217+
// impl rawhostcall.ProxyWASMHost: delegated from hostEmulator
218218
func (h *httpHostEmulator) httpHostEmulatorProxyGetHeaderMapPairs(mapType types.MapType, returnValueData **byte,
219219
returnValueSize *int) types.Status {
220220
active := proxywasm.VMStateGetActiveContextID()
@@ -239,7 +239,7 @@ func (h *httpHostEmulator) httpHostEmulatorProxyGetHeaderMapPairs(mapType types.
239239
return types.StatusOK
240240
}
241241

242-
// impl host rawhostcall.ProxyWASMHost
242+
// impl rawhostcall.ProxyWASMHost
243243
func (h *httpHostEmulator) ProxySetHeaderMapPairs(mapType types.MapType, mapData *byte, mapSize int) types.Status {
244244
m := proxywasm.DeserializeMap(proxywasm.RawBytePtrToByteSlice(mapData, mapSize))
245245
active := proxywasm.VMStateGetActiveContextID()
@@ -260,15 +260,15 @@ func (h *httpHostEmulator) ProxySetHeaderMapPairs(mapType types.MapType, mapData
260260
return types.StatusOK
261261
}
262262

263-
// impl host rawhostcall.ProxyWASMHost
263+
// impl rawhostcall.ProxyWASMHost
264264
func (h *httpHostEmulator) ProxyContinueStream(types.StreamType) types.Status {
265265
active := proxywasm.VMStateGetActiveContextID()
266266
stream := h.httpStreams[active]
267267
stream.action = types.ActionContinue
268268
return types.StatusOK
269269
}
270270

271-
// impl host rawhostcall.ProxyWASMHost
271+
// impl rawhostcall.ProxyWASMHost
272272
func (h *httpHostEmulator) ProxySendLocalResponse(statusCode uint32,
273273
statusCodeDetailData *byte, statusCodeDetailsSize int, bodyData *byte, bodySize int,
274274
headersData *byte, headersSize int, grpcStatus int32) types.Status {
@@ -284,15 +284,15 @@ func (h *httpHostEmulator) ProxySendLocalResponse(statusCode uint32,
284284
return types.StatusOK
285285
}
286286

287-
// impl host HostEmulator
287+
// impl HostEmulator
288288
func (h *httpHostEmulator) HttpFilterInitContext() (contextID uint32) {
289289
contextID = getNextContextID()
290290
proxywasm.ProxyOnContextCreate(contextID, rootContextID)
291291
h.httpStreams[contextID] = &httpStreamState{action: types.ActionContinue}
292292
return
293293
}
294294

295-
// impl host HostEmulator
295+
// impl HostEmulator
296296
func (h *httpHostEmulator) HttpFilterPutRequestHeaders(contextID uint32, headers [][2]string) {
297297
cs, ok := h.httpStreams[contextID]
298298
if !ok {
@@ -304,7 +304,7 @@ func (h *httpHostEmulator) HttpFilterPutRequestHeaders(contextID uint32, headers
304304
len(headers), false) // TODO: allow for specifying end_of_stream
305305
}
306306

307-
// impl host HostEmulator
307+
// impl HostEmulator
308308
func (h *httpHostEmulator) HttpFilterPutResponseHeaders(contextID uint32, headers [][2]string) {
309309
cs, ok := h.httpStreams[contextID]
310310
if !ok {
@@ -317,7 +317,7 @@ func (h *httpHostEmulator) HttpFilterPutResponseHeaders(contextID uint32, header
317317
len(headers), false) // TODO: allow for specifying end_of_stream
318318
}
319319

320-
// impl host HostEmulator
320+
// impl HostEmulator
321321
func (h *httpHostEmulator) HttpFilterPutRequestTrailers(contextID uint32, headers [][2]string) {
322322
cs, ok := h.httpStreams[contextID]
323323
if !ok {
@@ -328,7 +328,7 @@ func (h *httpHostEmulator) HttpFilterPutRequestTrailers(contextID uint32, header
328328
cs.action = proxywasm.ProxyOnRequestTrailers(contextID, len(headers))
329329
}
330330

331-
// impl host HostEmulator
331+
// impl HostEmulator
332332
func (h *httpHostEmulator) HttpFilterPutResponseTrailers(contextID uint32, headers [][2]string) {
333333
cs, ok := h.httpStreams[contextID]
334334
if !ok {
@@ -339,7 +339,7 @@ func (h *httpHostEmulator) HttpFilterPutResponseTrailers(contextID uint32, heade
339339
cs.action = proxywasm.ProxyOnResponseTrailers(contextID, len(headers))
340340
}
341341

342-
// impl host HostEmulator
342+
// impl HostEmulator
343343
func (h *httpHostEmulator) HttpFilterPutRequestBody(contextID uint32, body []byte) {
344344
cs, ok := h.httpStreams[contextID]
345345
if !ok {
@@ -351,7 +351,7 @@ func (h *httpHostEmulator) HttpFilterPutRequestBody(contextID uint32, body []byt
351351
len(body), false) // TODO: allow for specifying end_of_stream
352352
}
353353

354-
// impl host HostEmulator
354+
// impl HostEmulator
355355
func (h *httpHostEmulator) HttpFilterPutResponseBody(contextID uint32, body []byte) {
356356
cs, ok := h.httpStreams[contextID]
357357
if !ok {
@@ -363,12 +363,12 @@ func (h *httpHostEmulator) HttpFilterPutResponseBody(contextID uint32, body []by
363363
len(body), false) // TODO: allow for specifying end_of_stream
364364
}
365365

366-
// impl host HostEmulator
366+
// impl HostEmulator
367367
func (h *httpHostEmulator) HttpFilterCompleteHttpStream(contextID uint32) {
368368
proxywasm.ProxyOnDone(contextID)
369369
}
370370

371-
// impl host HostEmulator
371+
// impl HostEmulator
372372
func (h *httpHostEmulator) HttpFilterGetCurrentStreamAction(contextID uint32) types.Action {
373373
stream, ok := h.httpStreams[contextID]
374374
if !ok {
@@ -377,7 +377,7 @@ func (h *httpHostEmulator) HttpFilterGetCurrentStreamAction(contextID uint32) ty
377377
return stream.action
378378
}
379379

380-
// impl host HostEmulator
380+
// impl HostEmulator
381381
func (h *httpHostEmulator) HttpFilterGetSentLocalResponse(contextID uint32) *LocalHttpResponse {
382382
return h.httpStreams[contextID].sentLocalResponse
383383
}

proxytest/network.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func newNetworkHostEmulator() *networkHostEmulator {
3737
return host
3838
}
3939

40-
// impl host rawhostcall.ProxyWASMHost: delegated from hostEmulator
40+
// impl rawhostcall.ProxyWASMHost: delegated from hostEmulator
4141
func (n *networkHostEmulator) networkHostEmulatorProxyGetBufferBytes(bt types.BufferType, start int, maxSize int,
4242
returnBufferData **byte, returnBufferSize *int) types.Status {
4343

@@ -67,7 +67,7 @@ func (n *networkHostEmulator) networkHostEmulatorProxyGetBufferBytes(bt types.Bu
6767
return types.StatusOK
6868
}
6969

70-
// impl host HostEmulator
70+
// impl HostEmulator
7171
func (n *networkHostEmulator) NetworkFilterPutUpstreamData(contextID uint32, data []byte) {
7272
stream, ok := n.streamStates[contextID]
7373
if !ok {
@@ -90,7 +90,7 @@ func (n *networkHostEmulator) NetworkFilterPutUpstreamData(contextID uint32, dat
9090
}
9191
}
9292

93-
// impl host HostEmulator
93+
// impl HostEmulator
9494
func (n *networkHostEmulator) NetworkFilterPutDownstreamData(contextID uint32, data []byte) {
9595
stream, ok := n.streamStates[contextID]
9696
if !ok {
@@ -112,7 +112,7 @@ func (n *networkHostEmulator) NetworkFilterPutDownstreamData(contextID uint32, d
112112
}
113113
}
114114

115-
// impl host HostEmulator
115+
// impl HostEmulator
116116
func (n *networkHostEmulator) NetworkFilterInitConnection() (contextID uint32) {
117117
contextID = getNextContextID()
118118
proxywasm.ProxyOnContextCreate(contextID, rootContextID)
@@ -121,17 +121,17 @@ func (n *networkHostEmulator) NetworkFilterInitConnection() (contextID uint32) {
121121
return
122122
}
123123

124-
// impl host HostEmulator
124+
// impl HostEmulator
125125
func (n *networkHostEmulator) NetworkFilterCloseUpstreamConnection(contextID uint32) {
126126
proxywasm.ProxyOnUpstreamConnectionClose(contextID, types.PeerTypeLocal) // peerType will be removed in the next ABI
127127
}
128128

129-
// impl host HostEmulator
129+
// impl HostEmulator
130130
func (n *networkHostEmulator) NetworkFilterCloseDownstreamConnection(contextID uint32) {
131131
proxywasm.ProxyOnDownstreamConnectionClose(contextID, types.PeerTypeLocal) // peerType will be removed in the next ABI
132132
}
133133

134-
// impl host HostEmulator
134+
// impl HostEmulator
135135
func (n *networkHostEmulator) NetworkFilterCompleteConnection(contextID uint32) {
136136
proxywasm.ProxyOnDone(contextID)
137137
delete(n.streamStates, contextID)

0 commit comments

Comments
 (0)