Coverage for rust2rpm/tests/test_generator.py: 94%

122 statements  

« prev     ^ index     » next       coverage.py v7.6.7, created at 2024-11-26 13:52 +0100

1import os 

2import re 

3import textwrap 

4import time 

5from importlib import resources 

6from pathlib import Path 

7from typing import cast 

8 

9import pytest 

10from cargo2rpm.metadata import FeatureFlags, Metadata 

11 

12from rust2rpm.conf import TomlConf 

13from rust2rpm.generator import CrateTemplate, EpelEightTemplate, ProjectTemplate, WorkspaceTemplate 

14from rust2rpm.generator.common import cargo_args_from_flags, conf_to_cargo_test_commands, format_cargo_test_command 

15from rust2rpm.generator.epel8 import cargo_args_from_flags as caff_epel8 

16from rust2rpm.generator.epel8 import cargo_test_commands as ctc_epel8 

17from rust2rpm.metadata import guess_main_package 

18from rust2rpm.project import CrateProject, LocalProject, PatchFile 

19from rust2rpm.project.shared import file_name_auto_patch, file_name_manual_patch 

20from rust2rpm.sysinfo import Target 

21 

22FIXED_DATE = time.gmtime(12345) 

23 

24 

25@pytest.mark.parametrize( 

26 ("crate", "version", "conf"), 

27 [ 

28 ("cargo-c", "0.9.32+cargo-0.79.0", None), 

29 ("cxx-build", "1.0.71", None), 

30 ("dotenvy", "0.15.6", "dotenvy-0.15.7.rust2rpm.toml"), 

31 ("glib-sys", "0.17.2", "glib-sys-0.17.2.rust2rpm.toml"), 

32 ("nix", "0.24.1", "nix-0.24.1.rust2rpm.toml"), 

33 ("rand_core", "0.9.0-alpha.2", None), 

34 ("tokio", "1.19.2", "tokio-1.19.2.rust2rpm.toml"), 

35 ], 

36) 

37@pytest.mark.parametrize("target", ["plain", "fedora", "mageia", "opensuse"]) 

38def test_spec_file_render_crate(crate: str, version: str, conf: str | None, target: str): 

39 crate_name_version = f"{crate}-{version}" 

40 filename = f"{crate_name_version}.json" 

41 

42 real_path = resources.files("rust2rpm.tests.data.metadata").joinpath(filename) 

43 metadata = Metadata.from_json(real_path.read_text()) 

44 

45 project = CrateProject( 

46 name=crate, 

47 version=version, 

48 metadata=metadata, 

49 license_files=["LIC1", "LIC2"], 

50 doc_files=["DOC1", "DOC2"], 

51 auto_patch=PatchFile(file_name_auto_patch(crate), ["some"]), 

52 manual_patch=PatchFile(file_name_manual_patch(crate), ["content"]), 

53 vendor_tarball=None, 

54 compat=False, 

55 ) 

56 

57 if conf: 

58 toml_path = Path(str(resources.files("rust2rpm.tests.data.config").joinpath(conf))) 

59 tomlconf = TomlConf.load(toml_path, metadata.packages[0].get_feature_names()) 

60 else: 

61 tomlconf = TomlConf() 

62 

63 template = CrateTemplate( 

64 project=project, 

65 conf=tomlconf, 

66 target=Target(target), 

67 date=FIXED_DATE, 

68 packager="Jane Jane <jane@jane.org>", 

69 use_relative_license_paths=False, 

70 use_rpmautospec=target == "fedora", 

71 make_changelog_entry=True, 

72 ) 

73 

74 rendered = template.render() 

75 

76 rendered = re.sub("(# Generated by rust2rpm) .*", r"\1 NNN", rendered) 

77 

78 if target == "opensuse": 

79 spec_copyright_year = time.strftime("%Y") 

80 rendered = re.sub(rf"(Copyright \(c\)) {spec_copyright_year}", r"\1 XXXX", rendered) 

81 

82 fixture_path = resources.files("rust2rpm.tests.data.specs").joinpath(f"{crate_name_version}.{target}.spec") 

83 fixture_path = cast(Path, fixture_path) 

84 

85 if os.getenv("UPDATE_FIXTURES") == "1": # pragma nocover 

86 # helper mode to create test data 

87 fixture_path.write_text(rendered) 

88 

89 else: 

90 expected = fixture_path.read_text() 

91 assert rendered == expected 

92 

93 

94@pytest.mark.parametrize( 

95 ("filename", "conf"), 

96 [ 

97 ("bindgen-cli-0.69.4.json", "bindgen-cli-0.69.4.rust2rpm.toml"), 

98 ], 

99) 

100def test_spec_file_render_epel8(filename: str, conf: str | None): 

101 crate_name_version = filename.removesuffix(".json") 

102 crate, version = crate_name_version.rsplit("-", 1) 

103 

104 real_path = resources.files("rust2rpm.tests.data.metadata").joinpath(filename) 

105 metadata = Metadata.from_json(real_path.read_text()) 

106 

107 project = CrateProject( 

108 name=crate, 

109 version=version, 

110 metadata=metadata, 

111 license_files=["LIC1", "LIC2"], 

112 doc_files=["DOC1", "DOC2"], 

113 auto_patch=PatchFile(file_name_auto_patch(crate), ["some"]), 

114 manual_patch=PatchFile(file_name_manual_patch(crate), ["content"]), 

115 vendor_tarball="%{crate}-%{version}-vendor.tar.xz", 

116 compat=False, 

117 ) 

118 

119 if conf: 119 ↛ 123line 119 didn't jump to line 123 because the condition on line 119 was always true

120 toml_path = Path(str(resources.files("rust2rpm.tests.data.config").joinpath(conf))) 

121 tomlconf = TomlConf.load(toml_path, metadata.packages[0].get_feature_names()) 

122 else: 

123 tomlconf = TomlConf() 

124 

125 template = EpelEightTemplate( 

126 project=project, 

127 conf=tomlconf, 

128 date=FIXED_DATE, 

129 packager="Jane Jane <jane@jane.org>", 

130 use_rpmautospec=True, 

131 make_changelog_entry=True, 

132 ) 

133 

134 rendered = template.render() 

135 

136 rendered = re.sub("(# Generated by rust2rpm) .*", r"\1 NNN", rendered) 

137 

138 fixture_path = resources.files("rust2rpm.tests.data.specs").joinpath(f"{crate_name_version}.spec") 

139 fixture_path = cast(Path, fixture_path) 

140 

141 if os.getenv("UPDATE_FIXTURES") == "1": # pragma nocover 

142 # helper mode to create test data 

143 fixture_path.write_text(rendered) 

144 

145 else: 

146 expected = fixture_path.read_text() 

147 assert rendered == expected 

148 

149 

150@pytest.mark.parametrize( 

151 ("filename", "conf", "vendor_tarball"), 

152 [ 

153 ("rust2rpm-helper-0.1.3.json", None, None), 

154 ("stgit-2.3.3.json", None, "stgit-vendor-2.3.3.tar.xz"), 

155 ], 

156 ids=repr, 

157) 

158@pytest.mark.parametrize("target", ["plain", "fedora", "mageia", "opensuse"]) 

159def test_spec_file_render_project(filename: str, conf: str | None, vendor_tarball: str | None, target: str): 

160 crate_name_version = filename.removesuffix(".json") 

161 crate, version = crate_name_version.rsplit("-", 1) 

162 

163 real_path = resources.files("rust2rpm.tests.data.metadata").joinpath(filename) 

164 metadata = Metadata.from_json(real_path.read_text()) 

165 

166 project = LocalProject( 

167 name=crate, 

168 version=version, 

169 metadata=metadata, 

170 license_files=["LIC1", "LIC2"], 

171 doc_files=["DOC1", "DOC2"], 

172 auto_patch=PatchFile(file_name_auto_patch(crate), ["some"]), 

173 manual_patch=PatchFile(file_name_manual_patch(crate), ["content"]), 

174 vendor_tarball=vendor_tarball, 

175 main_package=metadata.packages[0], 

176 ) 

177 

178 if conf: 178 ↛ 179line 178 didn't jump to line 179 because the condition on line 178 was never true

179 toml_path = Path(str(resources.files("rust2rpm.tests.data.config").joinpath(conf))) 

180 tomlconf = TomlConf.load(toml_path, set()) 

181 else: 

182 tomlconf = TomlConf() 

183 

184 template = ProjectTemplate( 

185 project=project, 

186 conf=tomlconf, 

187 target=Target(target), 

188 date=FIXED_DATE, 

189 packager="Jane Jane <jane@jane.org>", 

190 use_rpmautospec=target == "fedora", 

191 make_changelog_entry=True, 

192 ) 

193 

194 rendered = template.render() 

195 

196 rendered = re.sub("(# Generated by rust2rpm) .*", r"\1 NNN", rendered) 

197 

198 if target == "opensuse": 

199 spec_copyright_year = time.strftime("%Y") 

200 rendered = re.sub(rf"(Copyright \(c\)) {spec_copyright_year}", r"\1 XXXX", rendered) 

201 

202 fixture_path = resources.files("rust2rpm.tests.data.specs").joinpath(f"{crate_name_version}.{target}.spec") 

203 fixture_path = cast(Path, fixture_path) 

204 

205 if os.getenv("UPDATE_FIXTURES") == "1": # pragma nocover 

206 # helper mode to create test data 

207 fixture_path.write_text(rendered) 

208 

209 else: 

210 expected = fixture_path.read_text() 

211 assert rendered == expected 

212 

213 

214@pytest.mark.parametrize( 

215 ("filename", "hint", "conf", "vendor_tarball"), 

216 [ 

217 ("system76-keyboard-configurator-1.3.9.json", "system76-keyboard-configurator", None, None), 

218 ("zola-0.16.1.json", "zola", None, "zola-0.16.1-vendor.tar.xz"), 

219 ], 

220) 

221@pytest.mark.parametrize("target", ["plain", "fedora", "mageia", "opensuse"]) 

222def test_spec_file_render_workspace( 

223 filename: str, 

224 hint: str, 

225 conf: str | None, 

226 vendor_tarball: str | None, 

227 target: str, 

228): 

229 crate_name_version = filename.removesuffix(".json") 

230 crate, version = crate_name_version.rsplit("-", 1) 

231 

232 real_path = resources.files("rust2rpm.tests.data.metadata").joinpath(filename) 

233 metadata = Metadata.from_json(real_path.read_text()) 

234 

235 project = LocalProject( 

236 name=crate, 

237 version=version, 

238 metadata=metadata, 

239 license_files=["LIC1", "LIC2"], 

240 doc_files=["DOC1", "DOC2"], 

241 auto_patch=PatchFile(file_name_auto_patch(crate), ["some"]), 

242 manual_patch=PatchFile(file_name_manual_patch(crate), ["content"]), 

243 vendor_tarball=vendor_tarball, 

244 main_package=guess_main_package(metadata, hint, None), 

245 ) 

246 

247 if conf: 247 ↛ 248line 247 didn't jump to line 248 because the condition on line 247 was never true

248 toml_path = Path(str(resources.files("rust2rpm.tests.data.config").joinpath(conf))) 

249 tomlconf = TomlConf.load(toml_path, metadata.packages[0].get_feature_names()) 

250 else: 

251 tomlconf = TomlConf() 

252 

253 template = WorkspaceTemplate( 

254 project=project, 

255 conf=tomlconf, 

256 target=Target(target), 

257 date=FIXED_DATE, 

258 packager="Jane Jane <jane@jane.org>", 

259 use_rpmautospec=target == "fedora", 

260 make_changelog_entry=True, 

261 ) 

262 

263 rendered = template.render() 

264 

265 rendered = re.sub("(# Generated by rust2rpm) .*", r"\1 NNN", rendered) 

266 

267 if target == "opensuse": 

268 spec_copyright_year = time.strftime("%Y") 

269 rendered = re.sub(rf"(Copyright \(c\)) {spec_copyright_year}", r"\1 XXXX", rendered) 

270 

271 fixture_path = resources.files("rust2rpm.tests.data.specs").joinpath(f"{crate_name_version}.{target}.spec") 

272 fixture_path = cast(Path, fixture_path) 

273 

274 if os.getenv("UPDATE_FIXTURES") == "1": # pragma nocover 

275 # helper mode to create test data 

276 fixture_path.write_text(rendered) 

277 

278 else: 

279 expected = fixture_path.read_text() 

280 assert rendered == expected 

281 

282 

283@pytest.mark.parametrize( 

284 ("flags", "required", "enabled", "expected"), 

285 [ 

286 (FeatureFlags(), set(), set(), ""), 

287 (FeatureFlags(), {"test"}, set(), " -f test"), 

288 (FeatureFlags(features=["test"]), {"test"}, set(), " -f test"), 

289 (FeatureFlags(features=["test"]), set(), {"test"}, " -f test"), 

290 (FeatureFlags(), {"test"}, {"test"}, ""), 

291 (FeatureFlags(), {"test1"}, {"test2"}, " -f test1"), 

292 (FeatureFlags(no_default_features=True), {"test"}, set(), " -n -f test"), 

293 (FeatureFlags(no_default_features=True, features=["test"]), {"test"}, set(), " -n -f test"), 

294 (FeatureFlags(no_default_features=True, features=["test"]), set(), {"test"}, " -n -f test"), 

295 (FeatureFlags(no_default_features=True), {"test"}, {"test"}, " -n"), 

296 (FeatureFlags(all_features=True), set(), set(), " -a"), 

297 (FeatureFlags(no_default_features=True), set(), set(), " -n"), 

298 (FeatureFlags(no_default_features=True, features=["test1", "test2"]), set(), set(), " -n -f test1,test2"), 

299 ], 

300 ids=repr, 

301) 

302def test_cargo_args_from_flags(flags: FeatureFlags, required: set[str], enabled: set[str], expected: str): 

303 assert cargo_args_from_flags(flags, required, enabled) == expected 

304 

305 

306@pytest.mark.parametrize( 

307 ("filename", "features", "expected"), 

308 [ 

309 ( 

310 "dotenvy-0.15.7.rust2rpm.toml", 

311 set(), 

312 [ 

313 "# * files required by doctests are not included in published crates", 

314 "%cargo_test -- --lib", 

315 "%cargo_test -- --tests", 

316 ], 

317 ), 

318 ( 

319 "reqwest-0.11.20.rust2rpm.toml", 

320 set(), 

321 [ 

322 textwrap.dedent( 

323 """\ 

324 # * skip tests which require internet access 

325 %{cargo_test -- -- --exact %{shrink: 

326 --skip test_allowed_methods 

327 --skip test_badssl_modern 

328 --skip test_badssl_self_signed 

329 }}""", 

330 ), 

331 ], 

332 ), 

333 ], 

334 ids=repr, 

335) 

336def test_conf_to_cargo_test_args(filename: str, features: set[str], expected: str): 

337 path = Path(str(resources.files("rust2rpm.tests.data.config").joinpath(filename))) 

338 conf = TomlConf.load(path, features) 

339 assert conf_to_cargo_test_commands(conf, "") == expected 

340 

341 

342@pytest.mark.parametrize( 

343 ("filename", "features", "expected"), 

344 [ 

345 ( 

346 "dotenvy-0.15.7.rust2rpm.toml", 

347 set(), 

348 [ 

349 "%cargo_test --lib", 

350 "%cargo_test --tests", 

351 ], 

352 ), 

353 ( 

354 "reqwest-0.11.20.rust2rpm.toml", 

355 set(), 

356 [ 

357 "%cargo_test -- --exact " 

358 "--skip test_allowed_methods --skip test_badssl_modern --skip test_badssl_self_signed", 

359 ], 

360 ), 

361 ], 

362 ids=repr, 

363) 

364def test_conf_to_cargo_test_args_epel8(filename: str, features: set[str], expected: str): 

365 path = Path(str(resources.files("rust2rpm.tests.data.config").joinpath(filename))) 

366 conf = TomlConf.load(path, features) 

367 assert ctc_epel8(conf) == expected 

368 

369 

370@pytest.mark.parametrize( 

371 ("flags", "required", "enabled", "expected"), 

372 [ 

373 (FeatureFlags(), set(), set(), ""), 

374 (FeatureFlags(), {"test"}, set(), " --features test"), 

375 (FeatureFlags(features=["test"]), {"test"}, set(), " --features test"), 

376 (FeatureFlags(features=["test"]), set(), {"test"}, " --features test"), 

377 (FeatureFlags(), {"test"}, {"test"}, ""), 

378 (FeatureFlags(), {"test1"}, {"test2"}, " --features test1"), 

379 (FeatureFlags(no_default_features=True), {"test"}, set(), " --no-default-features --features test"), 

380 ( 

381 FeatureFlags(no_default_features=True, features=["test"]), 

382 {"test"}, 

383 set(), 

384 " --no-default-features --features test", 

385 ), 

386 ( 

387 FeatureFlags(no_default_features=True, features=["test"]), 

388 set(), 

389 {"test"}, 

390 " --no-default-features --features test", 

391 ), 

392 (FeatureFlags(no_default_features=True), {"test"}, {"test"}, " --no-default-features"), 

393 (FeatureFlags(all_features=True), set(), set(), " --all-features"), 

394 (FeatureFlags(no_default_features=True), set(), set(), " --no-default-features"), 

395 ( 

396 FeatureFlags(no_default_features=True, features=["test1", "test2"]), 

397 set(), 

398 set(), 

399 " --no-default-features --features test1,test2", 

400 ), 

401 ], 

402 ids=repr, 

403) 

404def test_cargo_args_from_flags_epel8(flags: FeatureFlags, required: set[str], enabled: set[str], expected: str): 

405 assert caff_epel8(flags, required, enabled) == expected 

406 

407 

408@pytest.mark.parametrize( 

409 ("kind", "cargo_args", "skip_exact", "skip", "comments", "expected"), 

410 [ 

411 ( 

412 None, 

413 "", 

414 False, 

415 [], 

416 [], 

417 "%cargo_test", 

418 ), 

419 ( 

420 "lib", 

421 " -a", 

422 True, 

423 ["foo"], 

424 ["hello"], 

425 textwrap.dedent( 

426 """\ 

427 # * hello 

428 %cargo_test -a -- --lib -- --exact --skip foo""", 

429 ), 

430 ), 

431 ( 

432 "lib", 

433 " -f baz", 

434 False, 

435 ["foo", "bar"], 

436 ["hello", "world"], 

437 textwrap.dedent( 

438 """\ 

439 # * hello 

440 # * world 

441 %{cargo_test -f baz -- --lib -- %{shrink: 

442 --skip foo 

443 --skip bar 

444 }}""", 

445 ), 

446 ), 

447 ], 

448) 

449def test_format_cargo_test_command( 

450 kind: str | None, 

451 cargo_args: str, 

452 skip_exact: bool, # noqa: FBT001 

453 skip: list[str], 

454 comments: list[str], 

455 expected: str, 

456): 

457 assert ( 

458 format_cargo_test_command(kind=kind, cargo_args=cargo_args, skip_exact=skip_exact, skip=skip, comments=comments) 

459 == expected 

460 )