wa-lang.org/wazero@v1.0.2/imports/proxywasm/_hostcall_test.go (about) 1 // Copyright 2021 Tetrate 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package proxywasm 16 17 import ( 18 "testing" 19 20 "github.com/stretchr/testify/require" 21 22 "wa-lang.org/wazero/imports/proxywasm/internal" 23 ) 24 25 type logHost struct { 26 internal.DefaultProxyWAMSHost 27 t *testing.T 28 expMessage string 29 expLogLevel internal.LogLevel 30 } 31 32 func (l logHost) ProxyLog(logLevel internal.LogLevel, messageData *byte, messageSize int) internal.Status { 33 actual := internal.RawBytePtrToString(messageData, messageSize) 34 require.Equal(l.t, l.expMessage, actual) 35 require.Equal(l.t, l.expLogLevel, logLevel) 36 return internal.StatusOK 37 } 38 39 func TestHostCall_ForeignFunction(t *testing.T) { 40 defer internal.RegisterMockWasmHost(internal.DefaultProxyWAMSHost{})() 41 42 ret, err := CallForeignFunction("testFunc", []byte("")) 43 require.NoError(t, err) 44 require.Equal(t, []byte(nil), ret) 45 } 46 47 func TestHostCall_Logging(t *testing.T) { 48 t.Run("trace", func(t *testing.T) { 49 release := internal.RegisterMockWasmHost(logHost{ 50 DefaultProxyWAMSHost: internal.DefaultProxyWAMSHost{}, 51 t: t, 52 expMessage: "trace", 53 expLogLevel: internal.LogLevelTrace, 54 }) 55 defer release() 56 LogTrace("trace") 57 }) 58 59 t.Run("tracef", func(t *testing.T) { 60 release := internal.RegisterMockWasmHost(logHost{ 61 DefaultProxyWAMSHost: internal.DefaultProxyWAMSHost{}, 62 t: t, 63 expMessage: "trace: log", 64 expLogLevel: internal.LogLevelTrace, 65 }) 66 defer release() 67 LogTracef("trace: %s", "log") 68 }) 69 70 t.Run("debug", func(t *testing.T) { 71 release := internal.RegisterMockWasmHost(logHost{ 72 DefaultProxyWAMSHost: internal.DefaultProxyWAMSHost{}, 73 t: t, 74 expMessage: "abc", 75 expLogLevel: internal.LogLevelDebug, 76 }) 77 defer release() 78 LogDebug("abc") 79 }) 80 81 t.Run("debugf", func(t *testing.T) { 82 release := internal.RegisterMockWasmHost(logHost{ 83 DefaultProxyWAMSHost: internal.DefaultProxyWAMSHost{}, 84 t: t, 85 expMessage: "debug: log", 86 expLogLevel: internal.LogLevelDebug, 87 }) 88 defer release() 89 LogDebugf("debug: %s", "log") 90 }) 91 92 t.Run("info", func(t *testing.T) { 93 release := internal.RegisterMockWasmHost(logHost{ 94 DefaultProxyWAMSHost: internal.DefaultProxyWAMSHost{}, 95 t: t, 96 expMessage: "info", 97 expLogLevel: internal.LogLevelInfo, 98 }) 99 defer release() 100 LogInfo("info") 101 }) 102 103 t.Run("infof", func(t *testing.T) { 104 release := internal.RegisterMockWasmHost(logHost{ 105 DefaultProxyWAMSHost: internal.DefaultProxyWAMSHost{}, 106 t: t, 107 expMessage: "info: log: 10", 108 expLogLevel: internal.LogLevelInfo, 109 }) 110 defer release() 111 LogInfof("info: %s: %d", "log", 10) 112 }) 113 114 t.Run("warn", func(t *testing.T) { 115 release := internal.RegisterMockWasmHost(logHost{ 116 DefaultProxyWAMSHost: internal.DefaultProxyWAMSHost{}, 117 t: t, 118 expMessage: "warn", 119 expLogLevel: internal.LogLevelWarn, 120 }) 121 defer release() 122 LogWarn("warn") 123 }) 124 125 t.Run("warnf", func(t *testing.T) { 126 release := internal.RegisterMockWasmHost(logHost{ 127 DefaultProxyWAMSHost: internal.DefaultProxyWAMSHost{}, 128 t: t, 129 expMessage: "warn: log: 10", 130 expLogLevel: internal.LogLevelWarn, 131 }) 132 defer release() 133 LogWarnf("warn: %s: %d", "log", 10) 134 }) 135 136 t.Run("error", func(t *testing.T) { 137 release := internal.RegisterMockWasmHost(logHost{ 138 DefaultProxyWAMSHost: internal.DefaultProxyWAMSHost{}, 139 t: t, 140 expMessage: "error", 141 expLogLevel: internal.LogLevelError, 142 }) 143 defer release() 144 LogError("error") 145 }) 146 147 t.Run("warnf", func(t *testing.T) { 148 release := internal.RegisterMockWasmHost(logHost{ 149 DefaultProxyWAMSHost: internal.DefaultProxyWAMSHost{}, 150 t: t, 151 expMessage: "warn: log: 10", 152 expLogLevel: internal.LogLevelWarn, 153 }) 154 defer release() 155 LogWarnf("warn: %s: %d", "log", 10) 156 }) 157 158 t.Run("critical", func(t *testing.T) { 159 release := internal.RegisterMockWasmHost(logHost{ 160 DefaultProxyWAMSHost: internal.DefaultProxyWAMSHost{}, 161 t: t, 162 expMessage: "critical error", 163 expLogLevel: internal.LogLevelCritical, 164 }) 165 defer release() 166 LogCritical("critical error") 167 }) 168 169 t.Run("criticalf", func(t *testing.T) { 170 release := internal.RegisterMockWasmHost(logHost{ 171 DefaultProxyWAMSHost: internal.DefaultProxyWAMSHost{}, 172 t: t, 173 expMessage: "critical: log: 10", 174 expLogLevel: internal.LogLevelCritical, 175 }) 176 defer release() 177 LogCriticalf("critical: %s: %d", "log", 10) 178 }) 179 } 180 181 type metricProxyWasmHost struct { 182 internal.DefaultProxyWAMSHost 183 idToValue map[uint32]uint64 184 idToType map[uint32]internal.MetricType 185 nameToID map[string]uint32 186 } 187 188 func (m metricProxyWasmHost) ProxyDefineMetric(metricType internal.MetricType, 189 metricNameData *byte, metricNameSize int, returnMetricIDPtr *uint32) internal.Status { 190 name := internal.RawBytePtrToString(metricNameData, metricNameSize) 191 id, ok := m.nameToID[name] 192 if !ok { 193 id = uint32(len(m.nameToID)) 194 m.nameToID[name] = id 195 m.idToValue[id] = 0 196 m.idToType[id] = metricType 197 } 198 *returnMetricIDPtr = id 199 return internal.StatusOK 200 } 201 202 func (m metricProxyWasmHost) ProxyIncrementMetric(metricID uint32, offset int64) internal.Status { 203 val, ok := m.idToValue[metricID] 204 if !ok { 205 return internal.StatusBadArgument 206 } 207 208 m.idToValue[metricID] = val + uint64(offset) 209 return internal.StatusOK 210 } 211 212 func (m metricProxyWasmHost) ProxyRecordMetric(metricID uint32, value uint64) internal.Status { 213 _, ok := m.idToValue[metricID] 214 if !ok { 215 return internal.StatusBadArgument 216 } 217 m.idToValue[metricID] = value 218 return internal.StatusOK 219 } 220 221 func (m metricProxyWasmHost) ProxyGetMetric(metricID uint32, returnMetricValue *uint64) internal.Status { 222 value, ok := m.idToValue[metricID] 223 if !ok { 224 return internal.StatusBadArgument 225 } 226 *returnMetricValue = value 227 return internal.StatusOK 228 } 229 230 func TestHostCall_Metric(t *testing.T) { 231 host := metricProxyWasmHost{ 232 internal.DefaultProxyWAMSHost{}, 233 map[uint32]uint64{}, 234 map[uint32]internal.MetricType{}, 235 map[string]uint32{}, 236 } 237 release := internal.RegisterMockWasmHost(host) 238 defer release() 239 240 t.Run("counter", func(t *testing.T) { 241 for _, c := range []struct { 242 name string 243 offset uint64 244 }{ 245 {name: "requests", offset: 100}, 246 } { 247 t.Run(c.name, func(t *testing.T) { 248 // define metric 249 m := DefineCounterMetric(c.name) 250 251 // increment 252 m.Increment(c.offset) 253 254 // get 255 require.Equal(t, c.offset, m.Value()) 256 }) 257 } 258 }) 259 260 t.Run("gauge", func(t *testing.T) { 261 for _, c := range []struct { 262 name string 263 offset int64 264 }{ 265 {name: "rate", offset: -50}, 266 } { 267 t.Run(c.name, func(t *testing.T) { 268 // define metric 269 m := DefineGaugeMetric(c.name) 270 271 // increment 272 m.Add(c.offset) 273 274 // get 275 require.Equal(t, c.offset, m.Value()) 276 }) 277 } 278 }) 279 280 t.Run("histogram", func(t *testing.T) { 281 for _, c := range []struct { 282 name string 283 value uint64 284 }{ 285 {name: "request count", value: 10000}, 286 } { 287 t.Run(c.name, func(t *testing.T) { 288 // define metric 289 m := DefineHistogramMetric(c.name) 290 291 // record 292 m.Record(c.value) 293 294 // get 295 require.Equal(t, c.value, m.Value()) 296 }) 297 } 298 }) 299 }