|
20 | 20 |
|
21 | 21 | #include "test/utility.h"
|
22 | 22 |
|
| 23 | +#include "src/wasm.h" |
| 24 | + |
23 | 25 | namespace proxy_wasm {
|
24 | 26 |
|
25 | 27 | INSTANTIATE_TEST_SUITE_P(WasmEngines, TestVm, testing::ValuesIn(getWasmEngines()),
|
@@ -242,4 +244,84 @@ TEST_P(TestVm, AlwaysApplyCanary) {
|
242 | 244 | }
|
243 | 245 | }
|
244 | 246 |
|
| 247 | +// Check that there are no stale thread-local cache keys (eventually) |
| 248 | +TEST_P(TestVm, CleanupThreadLocalCacheKeys) { |
| 249 | + const auto *const plugin_name = "plugin_name"; |
| 250 | + const auto *const root_id = "root_id"; |
| 251 | + const auto *const vm_id = "vm_id"; |
| 252 | + const auto *const vm_config = "vm_config"; |
| 253 | + const auto *const plugin_config = "plugin_config"; |
| 254 | + const auto fail_open = false; |
| 255 | + |
| 256 | + WasmHandleFactory wasm_handle_factory = |
| 257 | + [this, vm_id, vm_config](std::string_view vm_key) -> std::shared_ptr<WasmHandleBase> { |
| 258 | + auto base_wasm = std::make_shared<WasmBase>(makeVm(engine_), vm_id, vm_config, vm_key, |
| 259 | + std::unordered_map<std::string, std::string>{}, |
| 260 | + AllowedCapabilitiesMap{}); |
| 261 | + return std::make_shared<WasmHandleBase>(base_wasm); |
| 262 | + }; |
| 263 | + |
| 264 | + WasmHandleCloneFactory wasm_handle_clone_factory = |
| 265 | + [this](const std::shared_ptr<WasmHandleBase> &base_wasm_handle) |
| 266 | + -> std::shared_ptr<WasmHandleBase> { |
| 267 | + auto wasm = std::make_shared<WasmBase>( |
| 268 | + base_wasm_handle, [this]() -> std::unique_ptr<WasmVm> { return makeVm(engine_); }); |
| 269 | + return std::make_shared<WasmHandleBase>(wasm); |
| 270 | + }; |
| 271 | + |
| 272 | + PluginHandleFactory plugin_handle_factory = |
| 273 | + [](const std::shared_ptr<WasmHandleBase> &base_wasm, |
| 274 | + const std::shared_ptr<PluginBase> &plugin) -> std::shared_ptr<PluginHandleBase> { |
| 275 | + return std::make_shared<PluginHandleBase>(base_wasm, plugin); |
| 276 | + }; |
| 277 | + |
| 278 | + // Read the minimal loadable binary. |
| 279 | + auto source = readTestWasmFile("abi_export.wasm"); |
| 280 | + |
| 281 | + // Simulate a plugin lifetime. |
| 282 | + const auto plugin1 = std::make_shared<PluginBase>(plugin_name, root_id, vm_id, engine_, |
| 283 | + plugin_config, fail_open, "plugin_1"); |
| 284 | + auto base_wasm_handle1 = |
| 285 | + createWasm("vm_1", source, plugin1, wasm_handle_factory, wasm_handle_clone_factory, false); |
| 286 | + ASSERT_TRUE(base_wasm_handle1 && base_wasm_handle1->wasm()); |
| 287 | + |
| 288 | + auto local_plugin1 = getOrCreateThreadLocalPlugin( |
| 289 | + base_wasm_handle1, plugin1, wasm_handle_clone_factory, plugin_handle_factory); |
| 290 | + ASSERT_TRUE(local_plugin1 && local_plugin1->plugin()); |
| 291 | + local_plugin1.reset(); |
| 292 | + |
| 293 | + auto stale_plugins_keys = staleLocalPluginsKeysForTesting(); |
| 294 | + EXPECT_EQ(1, stale_plugins_keys.size()); |
| 295 | + |
| 296 | + // Now we create another plugin with a slightly different key and expect that there are no stale |
| 297 | + // thread-local cache entries. |
| 298 | + const auto plugin2 = std::make_shared<PluginBase>(plugin_name, root_id, vm_id, engine_, |
| 299 | + plugin_config, fail_open, "plugin_2"); |
| 300 | + auto local_plugin2 = getOrCreateThreadLocalPlugin( |
| 301 | + base_wasm_handle1, plugin2, wasm_handle_clone_factory, plugin_handle_factory); |
| 302 | + ASSERT_TRUE(local_plugin2 && local_plugin2->plugin()); |
| 303 | + |
| 304 | + stale_plugins_keys = staleLocalPluginsKeysForTesting(); |
| 305 | + EXPECT_TRUE(stale_plugins_keys.empty()); |
| 306 | + |
| 307 | + // Trigger deletion of the thread-local WasmVM cloned from base_wasm_handle1 by freeing objects |
| 308 | + // referencing it. |
| 309 | + local_plugin2.reset(); |
| 310 | + |
| 311 | + auto stale_wasms_keys = staleLocalWasmsKeysForTesting(); |
| 312 | + EXPECT_EQ(1, stale_wasms_keys.size()); |
| 313 | + |
| 314 | + // Create another base WASM handle and invoke WASM thread-local cache key cleanup. |
| 315 | + auto base_wasm_handle2 = |
| 316 | + createWasm("vm_2", source, plugin2, wasm_handle_factory, wasm_handle_clone_factory, false); |
| 317 | + ASSERT_TRUE(base_wasm_handle2 && base_wasm_handle2->wasm()); |
| 318 | + |
| 319 | + auto local_plugin3 = getOrCreateThreadLocalPlugin( |
| 320 | + base_wasm_handle2, plugin2, wasm_handle_clone_factory, plugin_handle_factory); |
| 321 | + ASSERT_TRUE(local_plugin3 && local_plugin3->plugin()); |
| 322 | + |
| 323 | + stale_wasms_keys = staleLocalWasmsKeysForTesting(); |
| 324 | + EXPECT_TRUE(stale_wasms_keys.empty()); |
| 325 | +} |
| 326 | + |
245 | 327 | } // namespace proxy_wasm
|
0 commit comments