Skip to content

Commit b7e6907

Browse files
authored
Added tests for thread-local caches cleanup. (#362)
Signed-off-by: Maxim Philippov <[email protected]>
1 parent 356ea6e commit b7e6907

File tree

4 files changed

+128
-0
lines changed

4 files changed

+128
-0
lines changed

BUILD

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ cc_library(
7676
"src/signature_util.cc",
7777
"src/vm_id_handle.cc",
7878
"src/wasm.cc",
79+
"src/wasm.h",
7980
],
8081
hdrs = [
8182
"include/proxy-wasm/bytecode_util.h",

src/wasm.cc

+20
Original file line numberDiff line numberDiff line change
@@ -670,4 +670,24 @@ void clearWasmCachesForTesting() {
670670
}
671671
}
672672

673+
std::vector<std::string> staleLocalPluginsKeysForTesting() {
674+
std::vector<std::string> keys;
675+
for (const auto &kv : local_plugins) {
676+
if (kv.second.expired()) {
677+
keys.push_back(kv.first);
678+
}
679+
}
680+
return keys;
681+
}
682+
683+
std::vector<std::string> staleLocalWasmsKeysForTesting() {
684+
std::vector<std::string> keys;
685+
for (const auto &kv : local_wasms) {
686+
if (kv.second.expired()) {
687+
keys.push_back(kv.first);
688+
}
689+
}
690+
return keys;
691+
}
692+
673693
} // namespace proxy_wasm

src/wasm.h

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2023 Google LLC
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+
#pragma once
16+
17+
#include <string>
18+
#include <vector>
19+
20+
namespace proxy_wasm {
21+
22+
std::vector<std::string> staleLocalWasmsKeysForTesting();
23+
std::vector<std::string> staleLocalPluginsKeysForTesting();
24+
25+
} // namespace proxy_wasm

test/wasm_test.cc

+82
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
#include "test/utility.h"
2222

23+
#include "src/wasm.h"
24+
2325
namespace proxy_wasm {
2426

2527
INSTANTIATE_TEST_SUITE_P(WasmEngines, TestVm, testing::ValuesIn(getWasmEngines()),
@@ -242,4 +244,84 @@ TEST_P(TestVm, AlwaysApplyCanary) {
242244
}
243245
}
244246

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+
245327
} // namespace proxy_wasm

0 commit comments

Comments
 (0)