forjar 1.4.2

Rust-native Infrastructure as Code — bare-metal first, BLAKE3 state, provenance tracing
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
#![allow(unused_imports)]
use super::package::*;
use super::tests_package::make_apt_resource;
use crate::core::types::{MachineTarget, Resource, ResourceType};

#[test]
fn test_fj006_state_query_cargo_output_format() {
    let mut r = make_apt_resource(&["pmat"]);
    r.provider = Some("cargo".to_string());
    let script = state_query_script(&r);
    assert!(script.contains("echo 'pmat=installed'"));
    assert!(script.contains("echo 'pmat=MISSING'"));
}

/// BH-MUT-0003: Kill mutation of apt state_query_script format.
#[test]
fn test_fj006_state_query_apt_output_format() {
    let r = make_apt_resource(&["vim"]);
    let script = state_query_script(&r);
    assert!(script.contains("vim"));
    assert!(script.contains("vim=MISSING"));
    assert!(script.contains("dpkg-query -W"));
}

/// BH-MUT: Multi-package list preserves order.
#[test]
fn test_fj006_multi_package_check_preserves_all() {
    let r = make_apt_resource(&["a", "b", "c"]);
    let script = check_script(&r);
    // All packages present in output
    assert!(script.contains("dpkg -l 'a'"));
    assert!(script.contains("dpkg -l 'b'"));
    assert!(script.contains("dpkg -l 'c'"));
    // Verify newline separation (multi-line script)
    assert_eq!(script.matches('\n').count(), 2);
}

/// BH-MUT: cargo install uses conditional check before installing.
#[test]
fn test_fj006_cargo_install_unconditional_force() {
    let mut r = make_apt_resource(&["tool"]);
    r.provider = Some("cargo".to_string());
    let script = apply_script(&r);
    // --force makes install idempotent; FJ-51 adds --root for cache staging
    assert!(script.contains("cargo install --force --locked --root"));
    assert!(script.contains("'tool'"));
}

#[test]
fn test_fj006_apt_version_constraint() {
    let mut r = make_apt_resource(&["nginx"]);
    r.version = Some("1.18.0-0ubuntu1".to_string());
    let script = apply_script(&r);
    assert!(script.contains("'nginx=1.18.0-0ubuntu1'"));
    // Check commands still use unversioned name
    assert!(script.contains("dpkg -l \"$pkg\""));
}

#[test]
fn test_fj006_cargo_version_constraint() {
    let mut r = make_apt_resource(&["batuta"]);
    r.provider = Some("cargo".to_string());
    r.version = Some("0.3.0".to_string());
    let script = apply_script(&r);
    assert!(script.contains("cargo install --force --locked --root"));
    assert!(script.contains("'batuta@0.3.0'"));
}

#[test]
fn test_fj006_uv_version_constraint() {
    let mut r = make_apt_resource(&["ruff"]);
    r.provider = Some("uv".to_string());
    r.version = Some("0.4.0".to_string());
    let script = apply_script(&r);
    assert!(script.contains("uv tool install --force 'ruff==0.4.0'"));
}

#[test]
fn test_fj006_no_version_unchanged() {
    // Without version, scripts should be the same as before
    let r = make_apt_resource(&["curl"]);
    let script = apply_script(&r);
    assert!(script.contains("'curl'"));
    assert!(!script.contains("curl="));
}

#[test]
fn test_fj006_default_provider_is_apt() {
    let mut r = make_apt_resource(&["curl"]);
    r.provider = None; // Default
    let script = apply_script(&r);
    assert!(
        script.contains("apt-get install"),
        "default provider should be apt"
    );
}

#[test]
fn test_fj006_default_state_is_present() {
    let mut r = make_apt_resource(&["curl"]);
    r.state = None; // Default
    let script = apply_script(&r);
    assert!(
        script.contains("apt-get install"),
        "default state should be present (install)"
    );
    assert!(!script.contains("apt-get remove"));
}

#[test]
fn test_fj006_apt_idempotent_check() {
    // apt apply has pre-check: only runs install if needed
    let r = make_apt_resource(&["curl"]);
    let script = apply_script(&r);
    assert!(
        script.contains("NEED_INSTALL=0"),
        "must have idempotent check"
    );
    assert!(
        script.contains("NEED_INSTALL=1"),
        "must set flag when package missing"
    );
}

#[test]
fn test_fj006_apt_postcondition_verify() {
    // apt apply verifies all packages installed after install
    let r = make_apt_resource(&["curl", "wget"]);
    let script = apply_script(&r);
    // Postcondition check at end
    let last_dpkg = script.rfind("dpkg -l").unwrap();
    let install = script.find("apt-get install").unwrap();
    assert!(
        last_dpkg > install,
        "postcondition check must come after install"
    );
}

#[test]
fn test_fj006_uv_absent_tolerant() {
    // uv uninstall uses `|| true` to tolerate already-absent packages
    let mut r = make_apt_resource(&["ruff"]);
    r.provider = Some("uv".to_string());
    r.state = Some("absent".to_string());
    let script = apply_script(&r);
    assert!(
        script.contains("|| true"),
        "uv uninstall should tolerate already-absent"
    );
}

#[test]
fn test_fj006_cargo_absent_unsupported() {
    // cargo provider doesn't support absent state
    let mut r = make_apt_resource(&["tool"]);
    r.provider = Some("cargo".to_string());
    r.state = Some("absent".to_string());
    let script = apply_script(&r);
    assert!(
        script.contains("unsupported"),
        "cargo absent should be unsupported"
    );
}

/// FJ-1005: cargo provider bootstraps rustup if cargo is missing and sets PATH.
#[test]
fn test_fj1005_cargo_bootstrap_rustup() {
    let mut r = make_apt_resource(&["realizar"]);
    r.provider = Some("cargo".to_string());
    let script = apply_script(&r);
    assert!(
        script.contains("command -v cargo"),
        "must check if cargo exists: {script}"
    );
    assert!(
        script.contains("rustup.rs"),
        "must bootstrap via rustup: {script}"
    );
    assert!(
        script.contains("cargo install --force --locked --root"),
        "must still install (with --root for cache): {script}"
    );
    assert!(
        script.contains(".cargo/bin:$PATH"),
        "must add cargo to PATH: {script}"
    );
}

/// PMAT-043: rustup bootstrap must NOT pipe curl to sh (SEC008/SEC015 violation).
/// bashrs I8 validation rejects `curl | sh` patterns — download to tmpfile then execute.
#[test]
fn test_pmat043_rustup_no_curl_pipe_to_sh() {
    let mut r = make_apt_resource(&["realizar"]);
    r.provider = Some("cargo".to_string());
    let script = apply_script(&r);
    assert!(
        !script.contains("| sh"),
        "must not pipe curl to sh (SEC008): {script}"
    );
    assert!(
        !script.contains("| bash"),
        "must not pipe curl to bash: {script}"
    );
    // Should download to a file first, then execute
    assert!(
        script.contains("rustup-init"),
        "should download rustup-init to a file: {script}"
    );
}

/// FJ-1008: cargo install limits build parallelism to avoid OOM on high-core machines.
/// Root cause: unbounded `cargo install` defaults to nproc jobs, causing OOM on 32-core+.
#[test]
fn test_fj1008_cargo_install_limits_parallelism() {
    let mut r = make_apt_resource(&["realizar"]);
    r.provider = Some("cargo".to_string());
    let script = apply_script(&r);
    assert!(
        script.contains("CARGO_BUILD_JOBS"),
        "cargo install must set CARGO_BUILD_JOBS to limit parallelism: {script}"
    );
    assert!(
        script.contains("nproc"),
        "must derive job limit from nproc: {script}"
    );
}

// --- cargo source (--path) tests ---

/// cargo install from local source uses --path instead of crate name.
#[test]
fn test_fj_cargo_install_from_source() {
    let mut r = make_apt_resource(&["apr-cli"]);
    r.provider = Some("cargo".to_string());
    r.source = Some("/build/apr-cli".to_string());
    let script = apply_script(&r);
    assert!(
        script.contains("cargo install --force --locked --path '/build/apr-cli'"),
        "cargo source must use --path: {script}"
    );
    assert!(
        !script.contains("cargo install --force --locked 'apr-cli'"),
        "cargo source must NOT use crate name for install: {script}"
    );
}

/// When source is set, version is ignored (version comes from Cargo.toml at path).
#[test]
fn test_fj_cargo_source_ignores_version() {
    let mut r = make_apt_resource(&["apr-cli"]);
    r.provider = Some("cargo".to_string());
    r.source = Some("/build/apr-cli".to_string());
    r.version = Some("0.1.0".to_string());
    let script = apply_script(&r);
    assert!(
        script.contains("cargo install --force --locked --path '/build/apr-cli'"),
        "cargo source+version must still use --path: {script}"
    );
    assert!(
        !script.contains("@0.1.0"),
        "cargo source must ignore version: {script}"
    );
}

/// check_script still uses package name (binary name) even with source set.
#[test]
fn test_fj_cargo_source_check_uses_binary_name() {
    let mut r = make_apt_resource(&["apr-cli"]);
    r.provider = Some("cargo".to_string());
    r.source = Some("/build/apr-cli".to_string());
    let script = check_script(&r);
    assert!(
        script.contains("command -v 'apr-cli'"),
        "check_script must use package name even with source: {script}"
    );
}

// --- FJ-036: Additional package tests ---

#[test]
fn test_fj036_package_cargo_install_with_version() {
    let mut r = make_apt_resource(&["ripgrep"]);
    r.provider = Some("cargo".to_string());
    r.version = Some("14.1.0".to_string());
    let script = apply_script(&r);
    assert!(
        script.contains("cargo install --force --locked --root"),
        "cargo install with version must use --root for cache: {script}"
    );
    assert!(
        script.contains("'ripgrep@14.1.0'"),
        "cargo install with version must use @version syntax: {script}"
    );
}

#[test]
fn test_fj036_package_uv_install() {
    let mut r = make_apt_resource(&["ruff", "black"]);
    r.provider = Some("uv".to_string());
    let script = apply_script(&r);
    assert!(
        script.contains("uv tool install --force 'ruff'"),
        "uv provider must generate uv tool install: {script}"
    );
    assert!(
        script.contains("uv tool install --force 'black'"),
        "uv provider must install all packages: {script}"
    );
    assert!(
        script.contains("set -euo pipefail"),
        "uv install must start with safety flags: {script}"
    );
}

// ── Explicit per-arm match variant tests (apply_script) ───────

/// Match arm: ("apt", "present")
#[test]
fn test_apply_script_arm_apt_present() {
    let r = make_apt_resource(&["curl"]);
    let script = apply_script(&r);
    assert!(script.contains("apt-get install"), "apt present: {script}");
}

/// Match arm: ("apt", "absent")
#[test]
fn test_apply_script_arm_apt_absent() {
    let mut r = make_apt_resource(&["curl"]);
    r.state = Some("absent".to_string());
    let script = apply_script(&r);
    assert!(script.contains("apt-get remove"), "apt absent: {script}");
}

/// Match arm: ("apt", "latest") — PMAT-161
///
/// Latest semantics: refresh package lists then run apt-get install,
/// which installs missing packages or upgrades to the newest available
/// (no-op if already current). Postcondition: dpkg -l shows ii.
#[test]
fn test_apply_script_arm_apt_latest() {
    let mut r = make_apt_resource(&["docker-ce", "docker-ce-cli"]);
    r.state = Some("latest".to_string());
    let script = apply_script(&r);
    assert!(
        script.contains("apt-get update"),
        "apt latest must refresh lists: {script}"
    );
    assert!(
        script.contains("apt-get install"),
        "apt latest must install/upgrade: {script}"
    );
    assert!(
        script.contains("docker-ce") && script.contains("docker-ce-cli"),
        "apt latest must reference all packages: {script}"
    );
    assert!(
        !script.contains("unsupported"),
        "apt latest must not fall through to unsupported arm: {script}"
    );
    assert!(
        script.contains("set -euo pipefail"),
        "apt latest must use safety flags: {script}"
    );
    assert!(
        script.contains("dpkg -l"),
        "apt latest must verify postcondition via dpkg: {script}"
    );
    // FJ-PMAT-161-1: tolerate apt-get update partial failures
    assert!(
        script.contains("apt-get update -qq || true"),
        "apt latest must tolerate apt-get update failures: {script}"
    );
}

/// Match arm: ("cargo", "present")
#[test]
fn test_apply_script_arm_cargo_present() {
    let mut r = make_apt_resource(&["tool"]);
    r.provider = Some("cargo".to_string());
    let script = apply_script(&r);
    assert!(script.contains("cargo install"), "cargo present: {script}");
}

/// Match arm: ("uv", "present")
#[test]
fn test_apply_script_arm_uv_present() {
    let mut r = make_apt_resource(&["ruff"]);
    r.provider = Some("uv".to_string());
    let script = apply_script(&r);
    assert!(script.contains("uv tool install"), "uv present: {script}");
}

/// Match arm: ("uv", "absent")
#[test]
fn test_apply_script_arm_uv_absent() {
    let mut r = make_apt_resource(&["ruff"]);
    r.provider = Some("uv".to_string());
    r.state = Some("absent".to_string());
    let script = apply_script(&r);
    assert!(script.contains("uv tool uninstall"), "uv absent: {script}");
}

/// Match arm: (other_provider, other_state)
#[test]
fn test_apply_script_arm_other_provider_other_state() {
    let mut r = make_apt_resource(&["foo"]);
    r.provider = Some("pip".to_string());
    r.state = Some("present".to_string());
    let script = apply_script(&r);
    assert!(script.contains("unsupported"), "other arm: {script}");
}