v31.1-roots.1 · Commit 1: [PATCH 01/17] build(roots): establish v31 portability foundation
test/cmake/test_leveldb.py
Before: /dev/null · After: test/cmake/test_leveldb.py
File metadata
new file mode 100644 index 0000000000000000000000000000000000000000..b1614ac9b297a083bebff5398b6cb4484f655520
Download original patch · Release notes
Diff rows 1–122 of 122. Line numbers refer to the original before/after files.
+ Added− RemovedUnmarked lines are context.
Scroll the code area horizontally to read long lines. The two line-number columns refer to before and after.
test/cmake/test_leveldb.py
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Copyright (c) 2026-present The Bitcoin Roots developers
|
|
3
|
+
# Distributed under the MIT software license, see the accompanying
|
|
4
|
+
# file COPYING or https://opensource.org/license/mit/.
|
|
5
|
+
|
|
6
|
+
"""Exercise MemEnv discovery and consumer linkage with isolated fixture libraries.
|
|
7
|
+
|
|
8
|
+
These are finder regressions, not evidence of compatibility with a real system
|
|
9
|
+
LevelDB release. No package is installed and no host search paths are changed.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import argparse
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
import shutil
|
|
15
|
+
import subprocess
|
|
16
|
+
import tempfile
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def run(command, *, succeeds=True):
|
|
20
|
+
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
|
|
21
|
+
if (result.returncode == 0) != succeeds:
|
|
22
|
+
raise AssertionError(f"Unexpected result for {command}:\n{result.stdout}")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def main():
|
|
26
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
27
|
+
parser.add_argument("--cmake", required=True)
|
|
28
|
+
parser.add_argument("--compiler", required=True)
|
|
29
|
+
parser.add_argument("--generator", required=True)
|
|
30
|
+
parser.add_argument("--modules", required=True)
|
|
31
|
+
args = parser.parse_args()
|
|
32
|
+
with tempfile.TemporaryDirectory(prefix="roots-leveldb-") as directory:
|
|
33
|
+
root = Path(directory)
|
|
34
|
+
headers = root / "include"
|
|
35
|
+
(headers / "leveldb").mkdir(parents=True)
|
|
36
|
+
(headers / "leveldb/filter_policy.h").write_text("// Finder fixture.\n", encoding="utf8")
|
|
37
|
+
(headers / "leveldb/env.h").write_text(
|
|
38
|
+
"#pragma once\nnamespace leveldb { struct Env { virtual ~Env() = default; static Env* Default(); }; }\n",
|
|
39
|
+
encoding="utf8",
|
|
40
|
+
)
|
|
41
|
+
(headers / "memenv.h").write_text(
|
|
42
|
+
'#include <leveldb/env.h>\nnamespace leveldb { Env* NewMemEnv(Env*); }\n', encoding="utf8"
|
|
43
|
+
)
|
|
44
|
+
(root / "env.cpp").write_text(
|
|
45
|
+
'#include <leveldb/env.h>\nleveldb::Env* leveldb::Env::Default() { static Env env; return &env; }\n',
|
|
46
|
+
encoding="utf8",
|
|
47
|
+
)
|
|
48
|
+
(root / "memenv.cpp").write_text(
|
|
49
|
+
'#include <memenv.h>\nleveldb::Env* leveldb::NewMemEnv(Env*) { return new Env; }\n', encoding="utf8"
|
|
50
|
+
)
|
|
51
|
+
(root / "CMakeLists.txt").write_text(
|
|
52
|
+
"cmake_minimum_required(VERSION 3.22)\nproject(Fixture LANGUAGES CXX)\n"
|
|
53
|
+
"include_directories(include)\n"
|
|
54
|
+
"add_library(integrated STATIC env.cpp memenv.cpp)\n"
|
|
55
|
+
"add_library(base STATIC env.cpp)\nadd_library(helper STATIC memenv.cpp)\n", encoding="utf8"
|
|
56
|
+
)
|
|
57
|
+
fixture = root / "fixture"
|
|
58
|
+
run([args.cmake, "-S", str(root), "-B", str(fixture), "-G", args.generator,
|
|
59
|
+
f"-DCMAKE_CXX_COMPILER={args.compiler}"])
|
|
60
|
+
run([args.cmake, "--build", str(fixture), "--config", "Release", "-j2"])
|
|
61
|
+
# CMake controls the filename and multi-config output directory.
|
|
62
|
+
def library(name):
|
|
63
|
+
matches = [p for p in fixture.rglob(f"*{name}*") if p.suffix in (".a", ".lib")]
|
|
64
|
+
assert len(matches) == 1, matches
|
|
65
|
+
return matches[0]
|
|
66
|
+
|
|
67
|
+
consumer = root / "consumer"
|
|
68
|
+
consumer.mkdir()
|
|
69
|
+
(consumer / "main.cpp").write_text(
|
|
70
|
+
'#include <memenv.h>\nint main() { delete leveldb::NewMemEnv(leveldb::Env::Default()); }\n',
|
|
71
|
+
encoding="utf8",
|
|
72
|
+
)
|
|
73
|
+
(consumer / "CMakeLists.txt").write_text(
|
|
74
|
+
"cmake_minimum_required(VERSION 3.22)\nproject(Consumer LANGUAGES CXX)\n"
|
|
75
|
+
"list(APPEND CMAKE_MODULE_PATH \"${MODULES}\")\nfind_package(LevelDB REQUIRED)\n"
|
|
76
|
+
"add_executable(consumer main.cpp)\ntarget_link_libraries(consumer PRIVATE leveldb)\n", encoding="utf8"
|
|
77
|
+
)
|
|
78
|
+
for name, base, helper, succeeds in [
|
|
79
|
+
("integrated", library("integrated"), "", True),
|
|
80
|
+
("split", library("base"), library("helper"), True),
|
|
81
|
+
("missing-helper", library("base"), "LevelDB_MemEnv_LIBRARY_RELEASE-NOTFOUND", False),
|
|
82
|
+
("broken-debug-helper", library("integrated"), "", False),
|
|
83
|
+
]:
|
|
84
|
+
build = root / name
|
|
85
|
+
command = [args.cmake, "-S", str(consumer), "-B", str(build), "-DCMAKE_BUILD_TYPE=Release",
|
|
86
|
+
"-G", args.generator,
|
|
87
|
+
f"-DCMAKE_CXX_COMPILER={args.compiler}", f"-DMODULES={args.modules}",
|
|
88
|
+
f"-DCMAKE_FIND_ROOT_PATH={fixture}", "-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY",
|
|
89
|
+
f"-DLevelDB_INCLUDE_DIR={headers}", f"-DLevelDB_MemEnv_INCLUDE_DIR={headers}",
|
|
90
|
+
f"-DLevelDB_LIBRARY_RELEASE={base}",
|
|
91
|
+
f"-DLevelDB_LIBRARY_DEBUG={library('base') if name == 'broken-debug-helper' else 'LevelDB_LIBRARY_DEBUG-NOTFOUND'}",
|
|
92
|
+
f"-DLevelDB_MemEnv_LIBRARY_RELEASE={helper}",
|
|
93
|
+
"-DLevelDB_MemEnv_LIBRARY_DEBUG=LevelDB_MemEnv_LIBRARY_DEBUG-NOTFOUND"]
|
|
94
|
+
run(command, succeeds=succeeds)
|
|
95
|
+
if succeeds:
|
|
96
|
+
run([args.cmake, "--build", str(build), "--config", "Release", "-j2"])
|
|
97
|
+
print(f"PASS: {name} discovery and {'consumer linkage' if succeeds else 'rejection'}")
|
|
98
|
+
|
|
99
|
+
# Reuse one cache while switching between integrated and split packages.
|
|
100
|
+
# A cached empty helper from an integrated package must not suppress
|
|
101
|
+
# discovery of the separate helper after selecting another library.
|
|
102
|
+
helper_library = library("helper")
|
|
103
|
+
shutil.copyfile(helper_library, fixture / helper_library.name.replace("helper", "memenv"))
|
|
104
|
+
build = root / "reconfigured"
|
|
105
|
+
command = [args.cmake, "-S", str(consumer), "-B", str(build),
|
|
106
|
+
"-DCMAKE_BUILD_TYPE=Release", "-G", args.generator,
|
|
107
|
+
f"-DCMAKE_CXX_COMPILER={args.compiler}", f"-DMODULES={args.modules}",
|
|
108
|
+
f"-DCMAKE_LIBRARY_PATH={fixture}",
|
|
109
|
+
f"-DCMAKE_FIND_ROOT_PATH={fixture}", "-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY",
|
|
110
|
+
f"-DLevelDB_INCLUDE_DIR={headers}", f"-DLevelDB_MemEnv_INCLUDE_DIR={headers}",
|
|
111
|
+
"-DLevelDB_LIBRARY_DEBUG=LevelDB_LIBRARY_DEBUG-NOTFOUND",
|
|
112
|
+
"-DLevelDB_MemEnv_LIBRARY_DEBUG=LevelDB_MemEnv_LIBRARY_DEBUG-NOTFOUND"]
|
|
113
|
+
for index, name in enumerate(("integrated", "base", "integrated", "base")):
|
|
114
|
+
# Reproduce the cache entry written by the old finder as well.
|
|
115
|
+
legacy_cache = ["-DLevelDB_MemEnv_LIBRARY_RELEASE="] if index == 0 else []
|
|
116
|
+
run(command + [f"-DLevelDB_LIBRARY_RELEASE={library(name)}"] + legacy_cache)
|
|
117
|
+
run([args.cmake, "--build", str(build), "--config", "Release", "-j2"])
|
|
118
|
+
print("PASS: cache reconfiguration integrated/split discovery and consumer linkage")
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
if __name__ == "__main__":
|
|
122
|
+
main()
|