• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

loot / loot-condition-interpreter / 13091544509

01 Feb 2025 06:56PM UTC coverage: 89.787% (+0.4%) from 89.387%
13091544509

push

github

Ortham
Update versions and changelog for v5.0.0

4123 of 4592 relevant lines covered (89.79%)

15.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.49
/src/function/path.rs
1
use std::{
2
    ffi::OsStr,
3
    path::{Path, PathBuf},
4
};
5

6
use crate::{GameType, State};
7

8
const GHOST_EXTENSION: &str = "ghost";
9
const GHOST_EXTENSION_WITH_PERIOD: &str = ".ghost";
10

11
fn is_unghosted_plugin_file_extension(game_type: GameType, extension: &OsStr) -> bool {
152✔
12
    extension.eq_ignore_ascii_case("esp")
152✔
13
        || extension.eq_ignore_ascii_case("esm")
133✔
14
        || (game_type.supports_light_plugins() && extension.eq_ignore_ascii_case("esl"))
88✔
15
        || (game_type == GameType::OpenMW
84✔
16
            && (extension.eq_ignore_ascii_case("omwaddon")
7✔
17
                || extension.eq_ignore_ascii_case("omwgame")
6✔
18
                || extension.eq_ignore_ascii_case("omwscripts")))
5✔
19
}
152✔
20

21
fn has_unghosted_plugin_file_extension(game_type: GameType, path: &Path) -> bool {
91✔
22
    match path.extension() {
91✔
23
        Some(ext) => is_unghosted_plugin_file_extension(game_type, ext),
62✔
24
        _ => false,
29✔
25
    }
26
}
91✔
27

28
pub fn has_plugin_file_extension(game_type: GameType, path: &Path) -> bool {
14✔
29
    match path.extension() {
14✔
30
        Some(ext)
3✔
31
            if game_type.allows_ghosted_plugins() && ext.eq_ignore_ascii_case(GHOST_EXTENSION) =>
13✔
32
        {
3✔
33
            path.file_stem()
3✔
34
                .map(|s| has_unghosted_plugin_file_extension(game_type, Path::new(s)))
3✔
35
                .unwrap_or(false)
3✔
36
        }
37
        Some(ext) => is_unghosted_plugin_file_extension(game_type, ext),
10✔
38
        _ => false,
1✔
39
    }
40
}
14✔
41

42
fn add_ghost_extension(path: PathBuf) -> PathBuf {
6✔
43
    match path.extension() {
6✔
44
        Some(e) => {
5✔
45
            let mut new_extension = e.to_os_string();
5✔
46
            new_extension.push(GHOST_EXTENSION_WITH_PERIOD);
5✔
47
            path.with_extension(&new_extension)
5✔
48
        }
49
        None => path.with_extension(GHOST_EXTENSION),
1✔
50
    }
51
}
6✔
52

53
pub fn normalise_file_name(game_type: GameType, name: &OsStr) -> &OsStr {
78✔
54
    if !game_type.allows_ghosted_plugins() {
78✔
55
        return name;
1✔
56
    }
77✔
57

77✔
58
    let path = Path::new(name);
77✔
59
    if path
77✔
60
        .extension()
77✔
61
        .map(|s| s.eq_ignore_ascii_case(GHOST_EXTENSION))
77✔
62
        .unwrap_or(false)
77✔
63
    {
64
        // name ends in .ghost, trim it and then check the file extension.
65
        if let Some(stem) = path.file_stem() {
5✔
66
            if has_unghosted_plugin_file_extension(game_type, Path::new(stem)) {
5✔
67
                return stem;
4✔
68
            }
1✔
69
        }
×
70
    }
72✔
71

72
    name
73✔
73
}
78✔
74

75
pub fn resolve_path_in_parent_paths<'a>(
81✔
76
    path: &Path,
81✔
77
    parent_paths: impl Iterator<Item = &'a PathBuf>,
81✔
78
    try_with_ghost_extension: bool,
81✔
79
) -> Option<PathBuf> {
81✔
80
    for parent_path in parent_paths {
81✔
81
        let joined_path = parent_path.join(path);
2✔
82

2✔
83
        if joined_path.exists() {
2✔
84
            return Some(joined_path);
2✔
85
        }
×
86

×
87
        if try_with_ghost_extension {
×
88
            let ghosted_path = add_ghost_extension(joined_path);
×
89

×
90
            if ghosted_path.exists() {
×
91
                return Some(ghosted_path);
×
92
            }
×
93
        }
×
94
    }
95

96
    None
79✔
97
}
81✔
98

99
pub fn resolve_path(state: &State, path: &Path) -> PathBuf {
81✔
100
    let try_with_ghost_extension = state.game_type.allows_ghosted_plugins()
81✔
101
        && has_unghosted_plugin_file_extension(state.game_type, path);
79✔
102

103
    // OpenMW uses the last data directory that contains a matching path, with
104
    // the main data path being listed first, while for other games the first
105
    // additional data path that contains a matching path is used, and then the
106
    // main data path is checked.
107
    let result = match state.game_type {
81✔
108
        GameType::OpenMW => resolve_path_in_parent_paths(
2✔
109
            path,
2✔
110
            state.additional_data_paths.iter().rev(),
2✔
111
            try_with_ghost_extension,
2✔
112
        ),
2✔
113
        _ => resolve_path_in_parent_paths(
79✔
114
            path,
79✔
115
            state.additional_data_paths.iter(),
79✔
116
            try_with_ghost_extension,
79✔
117
        ),
79✔
118
    };
119

120
    if let Some(path) = result {
81✔
121
        return path;
2✔
122
    }
79✔
123

79✔
124
    // Now check the main data path.
79✔
125
    let joined_path = state.data_path.join(path);
79✔
126

79✔
127
    if !joined_path.exists() && try_with_ghost_extension {
79✔
128
        add_ghost_extension(joined_path)
4✔
129
    } else {
130
        joined_path
75✔
131
    }
132
}
81✔
133

134
#[cfg(test)]
135
mod tests {
136
    use super::*;
137

138
    #[test]
139
    fn is_unghosted_plugin_file_extension_should_be_true_for_esp_for_all_game_types() {
1✔
140
        let extension = OsStr::new("Esp");
1✔
141

1✔
142
        assert!(is_unghosted_plugin_file_extension(
1✔
143
            GameType::OpenMW,
1✔
144
            extension
1✔
145
        ));
1✔
146
        assert!(is_unghosted_plugin_file_extension(
1✔
147
            GameType::Morrowind,
1✔
148
            extension
1✔
149
        ));
1✔
150
        assert!(is_unghosted_plugin_file_extension(
1✔
151
            GameType::Oblivion,
1✔
152
            extension
1✔
153
        ));
1✔
154
        assert!(is_unghosted_plugin_file_extension(
1✔
155
            GameType::Skyrim,
1✔
156
            extension
1✔
157
        ));
1✔
158
        assert!(is_unghosted_plugin_file_extension(
1✔
159
            GameType::SkyrimSE,
1✔
160
            extension
1✔
161
        ));
1✔
162
        assert!(is_unghosted_plugin_file_extension(
1✔
163
            GameType::SkyrimVR,
1✔
164
            extension
1✔
165
        ));
1✔
166
        assert!(is_unghosted_plugin_file_extension(
1✔
167
            GameType::Fallout3,
1✔
168
            extension
1✔
169
        ));
1✔
170
        assert!(is_unghosted_plugin_file_extension(
1✔
171
            GameType::FalloutNV,
1✔
172
            extension
1✔
173
        ));
1✔
174
        assert!(is_unghosted_plugin_file_extension(
1✔
175
            GameType::Fallout4,
1✔
176
            extension
1✔
177
        ));
1✔
178
        assert!(is_unghosted_plugin_file_extension(
1✔
179
            GameType::Fallout4VR,
1✔
180
            extension
1✔
181
        ));
1✔
182
    }
1✔
183

184
    #[test]
185
    fn is_unghosted_plugin_file_extension_should_be_true_for_esm_for_all_game_types() {
1✔
186
        let extension = OsStr::new("Esm");
1✔
187

1✔
188
        assert!(is_unghosted_plugin_file_extension(
1✔
189
            GameType::OpenMW,
1✔
190
            extension
1✔
191
        ));
1✔
192
        assert!(is_unghosted_plugin_file_extension(
1✔
193
            GameType::Morrowind,
1✔
194
            extension
1✔
195
        ));
1✔
196
        assert!(is_unghosted_plugin_file_extension(
1✔
197
            GameType::Oblivion,
1✔
198
            extension
1✔
199
        ));
1✔
200
        assert!(is_unghosted_plugin_file_extension(
1✔
201
            GameType::Skyrim,
1✔
202
            extension
1✔
203
        ));
1✔
204
        assert!(is_unghosted_plugin_file_extension(
1✔
205
            GameType::SkyrimSE,
1✔
206
            extension
1✔
207
        ));
1✔
208
        assert!(is_unghosted_plugin_file_extension(
1✔
209
            GameType::SkyrimVR,
1✔
210
            extension
1✔
211
        ));
1✔
212
        assert!(is_unghosted_plugin_file_extension(
1✔
213
            GameType::Fallout3,
1✔
214
            extension
1✔
215
        ));
1✔
216
        assert!(is_unghosted_plugin_file_extension(
1✔
217
            GameType::FalloutNV,
1✔
218
            extension
1✔
219
        ));
1✔
220
        assert!(is_unghosted_plugin_file_extension(
1✔
221
            GameType::Fallout4,
1✔
222
            extension
1✔
223
        ));
1✔
224
        assert!(is_unghosted_plugin_file_extension(
1✔
225
            GameType::Fallout4VR,
1✔
226
            extension
1✔
227
        ));
1✔
228
    }
1✔
229

230
    #[test]
231
    fn is_unghosted_plugin_file_extension_should_be_true_for_esl_for_tes5se_tes5vr_fo4_and_fo4vr() {
1✔
232
        let extension = OsStr::new("Esl");
1✔
233

1✔
234
        assert!(is_unghosted_plugin_file_extension(
1✔
235
            GameType::SkyrimSE,
1✔
236
            extension
1✔
237
        ));
1✔
238
        assert!(is_unghosted_plugin_file_extension(
1✔
239
            GameType::SkyrimVR,
1✔
240
            extension
1✔
241
        ));
1✔
242
        assert!(is_unghosted_plugin_file_extension(
1✔
243
            GameType::Fallout4,
1✔
244
            extension
1✔
245
        ));
1✔
246
        assert!(is_unghosted_plugin_file_extension(
1✔
247
            GameType::Fallout4VR,
1✔
248
            extension
1✔
249
        ));
1✔
250
    }
1✔
251

252
    #[test]
253
    fn is_unghosted_plugin_file_extension_should_be_false_for_esl_for_tes3_to_5_fo3_and_fonv() {
1✔
254
        let extension = OsStr::new("Esl");
1✔
255

1✔
256
        assert!(!is_unghosted_plugin_file_extension(
1✔
257
            GameType::OpenMW,
1✔
258
            extension
1✔
259
        ));
1✔
260
        assert!(!is_unghosted_plugin_file_extension(
1✔
261
            GameType::Morrowind,
1✔
262
            extension
1✔
263
        ));
1✔
264
        assert!(!is_unghosted_plugin_file_extension(
1✔
265
            GameType::Oblivion,
1✔
266
            extension
1✔
267
        ));
1✔
268
        assert!(!is_unghosted_plugin_file_extension(
1✔
269
            GameType::Skyrim,
1✔
270
            extension
1✔
271
        ));
1✔
272
        assert!(!is_unghosted_plugin_file_extension(
1✔
273
            GameType::Fallout3,
1✔
274
            extension
1✔
275
        ));
1✔
276
        assert!(!is_unghosted_plugin_file_extension(
1✔
277
            GameType::FalloutNV,
1✔
278
            extension
1✔
279
        ));
1✔
280
    }
1✔
281

282
    #[test]
283
    fn is_unghosted_plugin_file_extension_should_be_true_for_omwaddon_and_only_openmw() {
1✔
284
        let extension = OsStr::new("omwaddon");
1✔
285

1✔
286
        assert!(is_unghosted_plugin_file_extension(
1✔
287
            GameType::OpenMW,
1✔
288
            extension
1✔
289
        ));
1✔
290

291
        assert!(!is_unghosted_plugin_file_extension(
1✔
292
            GameType::Morrowind,
1✔
293
            extension
1✔
294
        ));
1✔
295
        assert!(!is_unghosted_plugin_file_extension(
1✔
296
            GameType::Oblivion,
1✔
297
            extension
1✔
298
        ));
1✔
299
        assert!(!is_unghosted_plugin_file_extension(
1✔
300
            GameType::Skyrim,
1✔
301
            extension
1✔
302
        ));
1✔
303
        assert!(!is_unghosted_plugin_file_extension(
1✔
304
            GameType::SkyrimSE,
1✔
305
            extension
1✔
306
        ));
1✔
307
        assert!(!is_unghosted_plugin_file_extension(
1✔
308
            GameType::SkyrimVR,
1✔
309
            extension
1✔
310
        ));
1✔
311
        assert!(!is_unghosted_plugin_file_extension(
1✔
312
            GameType::Fallout3,
1✔
313
            extension
1✔
314
        ));
1✔
315
        assert!(!is_unghosted_plugin_file_extension(
1✔
316
            GameType::FalloutNV,
1✔
317
            extension
1✔
318
        ));
1✔
319
        assert!(!is_unghosted_plugin_file_extension(
1✔
320
            GameType::Fallout4,
1✔
321
            extension
1✔
322
        ));
1✔
323
        assert!(!is_unghosted_plugin_file_extension(
1✔
324
            GameType::Fallout4VR,
1✔
325
            extension
1✔
326
        ));
1✔
327
    }
1✔
328

329
    #[test]
330
    fn is_unghosted_plugin_file_extension_should_be_true_for_omwgame_and_only_openmw() {
1✔
331
        let extension = OsStr::new("omwgame");
1✔
332

1✔
333
        assert!(is_unghosted_plugin_file_extension(
1✔
334
            GameType::OpenMW,
1✔
335
            extension
1✔
336
        ));
1✔
337

338
        assert!(!is_unghosted_plugin_file_extension(
1✔
339
            GameType::Morrowind,
1✔
340
            extension
1✔
341
        ));
1✔
342
        assert!(!is_unghosted_plugin_file_extension(
1✔
343
            GameType::Oblivion,
1✔
344
            extension
1✔
345
        ));
1✔
346
        assert!(!is_unghosted_plugin_file_extension(
1✔
347
            GameType::Skyrim,
1✔
348
            extension
1✔
349
        ));
1✔
350
        assert!(!is_unghosted_plugin_file_extension(
1✔
351
            GameType::SkyrimSE,
1✔
352
            extension
1✔
353
        ));
1✔
354
        assert!(!is_unghosted_plugin_file_extension(
1✔
355
            GameType::SkyrimVR,
1✔
356
            extension
1✔
357
        ));
1✔
358
        assert!(!is_unghosted_plugin_file_extension(
1✔
359
            GameType::Fallout3,
1✔
360
            extension
1✔
361
        ));
1✔
362
        assert!(!is_unghosted_plugin_file_extension(
1✔
363
            GameType::FalloutNV,
1✔
364
            extension
1✔
365
        ));
1✔
366
        assert!(!is_unghosted_plugin_file_extension(
1✔
367
            GameType::Fallout4,
1✔
368
            extension
1✔
369
        ));
1✔
370
        assert!(!is_unghosted_plugin_file_extension(
1✔
371
            GameType::Fallout4VR,
1✔
372
            extension
1✔
373
        ));
1✔
374
    }
1✔
375

376
    #[test]
377
    fn is_unghosted_plugin_file_extension_should_be_true_for_omwscripts_and_only_openmw() {
1✔
378
        let extension = OsStr::new("omwscripts");
1✔
379

1✔
380
        assert!(is_unghosted_plugin_file_extension(
1✔
381
            GameType::OpenMW,
1✔
382
            extension
1✔
383
        ));
1✔
384

385
        assert!(!is_unghosted_plugin_file_extension(
1✔
386
            GameType::Morrowind,
1✔
387
            extension
1✔
388
        ));
1✔
389
        assert!(!is_unghosted_plugin_file_extension(
1✔
390
            GameType::Oblivion,
1✔
391
            extension
1✔
392
        ));
1✔
393
        assert!(!is_unghosted_plugin_file_extension(
1✔
394
            GameType::Skyrim,
1✔
395
            extension
1✔
396
        ));
1✔
397
        assert!(!is_unghosted_plugin_file_extension(
1✔
398
            GameType::SkyrimSE,
1✔
399
            extension
1✔
400
        ));
1✔
401
        assert!(!is_unghosted_plugin_file_extension(
1✔
402
            GameType::SkyrimVR,
1✔
403
            extension
1✔
404
        ));
1✔
405
        assert!(!is_unghosted_plugin_file_extension(
1✔
406
            GameType::Fallout3,
1✔
407
            extension
1✔
408
        ));
1✔
409
        assert!(!is_unghosted_plugin_file_extension(
1✔
410
            GameType::FalloutNV,
1✔
411
            extension
1✔
412
        ));
1✔
413
        assert!(!is_unghosted_plugin_file_extension(
1✔
414
            GameType::Fallout4,
1✔
415
            extension
1✔
416
        ));
1✔
417
        assert!(!is_unghosted_plugin_file_extension(
1✔
418
            GameType::Fallout4VR,
1✔
419
            extension
1✔
420
        ));
1✔
421
    }
1✔
422

423
    #[test]
424
    fn is_unghosted_plugin_file_extension_should_be_false_for_ghost_for_all_game_types() {
1✔
425
        let extension = OsStr::new("Ghost");
1✔
426

1✔
427
        assert!(!is_unghosted_plugin_file_extension(
1✔
428
            GameType::OpenMW,
1✔
429
            extension
1✔
430
        ));
1✔
431
        assert!(!is_unghosted_plugin_file_extension(
1✔
432
            GameType::Morrowind,
1✔
433
            extension
1✔
434
        ));
1✔
435
        assert!(!is_unghosted_plugin_file_extension(
1✔
436
            GameType::Oblivion,
1✔
437
            extension
1✔
438
        ));
1✔
439
        assert!(!is_unghosted_plugin_file_extension(
1✔
440
            GameType::Skyrim,
1✔
441
            extension
1✔
442
        ));
1✔
443
        assert!(!is_unghosted_plugin_file_extension(
1✔
444
            GameType::SkyrimSE,
1✔
445
            extension
1✔
446
        ));
1✔
447
        assert!(!is_unghosted_plugin_file_extension(
1✔
448
            GameType::SkyrimVR,
1✔
449
            extension
1✔
450
        ));
1✔
451
        assert!(!is_unghosted_plugin_file_extension(
1✔
452
            GameType::Fallout3,
1✔
453
            extension
1✔
454
        ));
1✔
455
        assert!(!is_unghosted_plugin_file_extension(
1✔
456
            GameType::FalloutNV,
1✔
457
            extension
1✔
458
        ));
1✔
459
        assert!(!is_unghosted_plugin_file_extension(
1✔
460
            GameType::Fallout4,
1✔
461
            extension
1✔
462
        ));
1✔
463
        assert!(!is_unghosted_plugin_file_extension(
1✔
464
            GameType::Fallout4VR,
1✔
465
            extension
1✔
466
        ));
1✔
467
    }
1✔
468

469
    #[test]
470
    fn is_unghosted_plugin_file_extension_should_be_false_for_non_esp_esm_esl_for_all_game_types() {
1✔
471
        let extension = OsStr::new("txt");
1✔
472

1✔
473
        assert!(!is_unghosted_plugin_file_extension(
1✔
474
            GameType::OpenMW,
1✔
475
            extension
1✔
476
        ));
1✔
477
        assert!(!is_unghosted_plugin_file_extension(
1✔
478
            GameType::Morrowind,
1✔
479
            extension
1✔
480
        ));
1✔
481
        assert!(!is_unghosted_plugin_file_extension(
1✔
482
            GameType::Oblivion,
1✔
483
            extension
1✔
484
        ));
1✔
485
        assert!(!is_unghosted_plugin_file_extension(
1✔
486
            GameType::Skyrim,
1✔
487
            extension
1✔
488
        ));
1✔
489
        assert!(!is_unghosted_plugin_file_extension(
1✔
490
            GameType::SkyrimSE,
1✔
491
            extension
1✔
492
        ));
1✔
493
        assert!(!is_unghosted_plugin_file_extension(
1✔
494
            GameType::SkyrimVR,
1✔
495
            extension
1✔
496
        ));
1✔
497
        assert!(!is_unghosted_plugin_file_extension(
1✔
498
            GameType::Fallout3,
1✔
499
            extension
1✔
500
        ));
1✔
501
        assert!(!is_unghosted_plugin_file_extension(
1✔
502
            GameType::FalloutNV,
1✔
503
            extension
1✔
504
        ));
1✔
505
        assert!(!is_unghosted_plugin_file_extension(
1✔
506
            GameType::Fallout4,
1✔
507
            extension
1✔
508
        ));
1✔
509
        assert!(!is_unghosted_plugin_file_extension(
1✔
510
            GameType::Fallout4VR,
1✔
511
            extension
1✔
512
        ));
1✔
513
    }
1✔
514

515
    #[test]
516
    fn has_unghosted_plugin_file_extension_should_return_false_if_the_path_has_no_extension() {
1✔
517
        assert!(!has_unghosted_plugin_file_extension(
1✔
518
            GameType::Skyrim,
1✔
519
            Path::new("file")
1✔
520
        ));
1✔
521
    }
1✔
522

523
    #[test]
524
    fn has_unghosted_plugin_file_extension_should_return_false_if_the_path_has_a_non_plugin_extension(
1✔
525
    ) {
1✔
526
        assert!(!has_unghosted_plugin_file_extension(
1✔
527
            GameType::Skyrim,
1✔
528
            Path::new("plugin.bsa")
1✔
529
        ));
1✔
530
    }
1✔
531

532
    #[test]
533
    fn has_unghosted_plugin_file_extension_should_return_false_if_the_path_has_a_ghosted_plugin_extension(
1✔
534
    ) {
1✔
535
        assert!(!has_unghosted_plugin_file_extension(
1✔
536
            GameType::Skyrim,
1✔
537
            Path::new("plugin.esp.ghost")
1✔
538
        ));
1✔
539
    }
1✔
540

541
    #[test]
542
    fn has_unghosted_plugin_file_extension_should_return_true_if_the_path_has_an_unghosted_plugin_extension(
1✔
543
    ) {
1✔
544
        assert!(has_unghosted_plugin_file_extension(
1✔
545
            GameType::Skyrim,
1✔
546
            Path::new("plugin.esp")
1✔
547
        ));
1✔
548
    }
1✔
549

550
    #[test]
551
    fn has_plugin_file_extension_should_return_true_if_the_path_has_an_unghosted_plugin_extension()
1✔
552
    {
1✔
553
        assert!(has_plugin_file_extension(
1✔
554
            GameType::Skyrim,
1✔
555
            Path::new("plugin.esp")
1✔
556
        ));
1✔
557
    }
1✔
558

559
    #[test]
560
    fn has_plugin_file_extension_should_return_true_if_the_path_has_a_ghosted_plugin_extension() {
1✔
561
        assert!(has_plugin_file_extension(
1✔
562
            GameType::Skyrim,
1✔
563
            Path::new("plugin.esp.Ghost")
1✔
564
        ));
1✔
565
    }
1✔
566

567
    #[test]
568
    fn has_plugin_file_extension_should_return_false_if_the_path_has_a_ghosted_plugin_extension_for_openmw(
1✔
569
    ) {
1✔
570
        assert!(!has_plugin_file_extension(
1✔
571
            GameType::OpenMW,
1✔
572
            Path::new("plugin.esp.Ghost")
1✔
573
        ));
1✔
574
    }
1✔
575

576
    #[test]
577
    fn has_plugin_file_extension_should_return_false_if_the_path_has_a_non_plugin_extension() {
1✔
578
        assert!(!has_plugin_file_extension(
1✔
579
            GameType::Skyrim,
1✔
580
            Path::new("plugin.bsa")
1✔
581
        ));
1✔
582
    }
1✔
583

584
    #[test]
585
    fn has_plugin_file_extension_should_return_false_if_the_path_has_a_ghosted_non_plugin_extension(
1✔
586
    ) {
1✔
587
        assert!(!has_plugin_file_extension(
1✔
588
            GameType::Skyrim,
1✔
589
            Path::new("plugin.bsa.Ghost")
1✔
590
        ));
1✔
591
    }
1✔
592

593
    #[test]
594
    fn has_plugin_file_extension_should_return_false_if_the_path_has_only_ghost_extension() {
1✔
595
        assert!(!has_plugin_file_extension(
1✔
596
            GameType::Skyrim,
1✔
597
            Path::new("plugin.Ghost")
1✔
598
        ));
1✔
599
    }
1✔
600

601
    #[test]
602
    fn has_plugin_file_extension_should_return_false_if_the_path_has_no_extension() {
1✔
603
        assert!(!has_plugin_file_extension(
1✔
604
            GameType::Skyrim,
1✔
605
            Path::new("plugin")
1✔
606
        ));
1✔
607
    }
1✔
608

609
    #[test]
610
    fn add_ghost_extension_should_add_dot_ghost_to_an_existing_extension() {
1✔
611
        let path = add_ghost_extension("plugin.esp".into());
1✔
612
        assert_eq!(PathBuf::from("plugin.esp.ghost"), path);
1✔
613
    }
1✔
614

615
    #[test]
616
    fn add_ghost_extension_should_add_dot_ghost_to_an_a_path_with_no_extension() {
1✔
617
        let path = add_ghost_extension("plugin".into());
1✔
618
        assert_eq!(PathBuf::from("plugin.ghost"), path);
1✔
619
    }
1✔
620

621
    #[test]
622
    fn normalise_file_name_should_remove_ghost_extension_from_a_plugin_filename() {
1✔
623
        assert_eq!(
1✔
624
            "plugin.esp",
1✔
625
            normalise_file_name(GameType::Oblivion, OsStr::new("plugin.esp.ghost"))
1✔
626
        );
1✔
627
    }
1✔
628

629
    #[test]
630
    fn normalise_file_name_should_not_remove_ghost_extension_from_a_non_plugin_filename() {
1✔
631
        assert_eq!(
1✔
632
            "plugin.ghost",
1✔
633
            normalise_file_name(GameType::Oblivion, OsStr::new("plugin.ghost"))
1✔
634
        );
1✔
635
    }
1✔
636

637
    #[test]
638
    fn normalise_file_name_should_return_a_non_ghost_extension_filename_unchanged() {
1✔
639
        assert_eq!(
1✔
640
            "plugin.esp",
1✔
641
            normalise_file_name(GameType::Oblivion, OsStr::new("plugin.esp"))
1✔
642
        );
1✔
643
    }
1✔
644

645
    #[test]
646
    fn normalise_file_name_should_return_the_path_unchanged_for_openmw() {
1✔
647
        assert_eq!(
1✔
648
            "plugin.esp.ghost",
1✔
649
            normalise_file_name(GameType::OpenMW, OsStr::new("plugin.esp.ghost"))
1✔
650
        );
1✔
651
    }
1✔
652

653
    #[test]
654
    fn resolve_path_should_return_the_data_path_prefixed_path_if_it_exists() {
1✔
655
        let data_path = PathBuf::from(".");
1✔
656
        let state = State::new(GameType::Skyrim, data_path.clone());
1✔
657
        let input_path = Path::new("README.md");
1✔
658
        let resolved_path = resolve_path(&state, input_path);
1✔
659

1✔
660
        assert_eq!(data_path.join(input_path), resolved_path);
1✔
661
    }
1✔
662

663
    #[test]
664
    fn resolve_path_should_return_the_data_path_prefixed_path_if_it_does_not_exist_and_is_not_an_unghosted_plugin_filename(
1✔
665
    ) {
1✔
666
        let data_path = PathBuf::from(".");
1✔
667
        let state = State::new(GameType::Skyrim, data_path.clone());
1✔
668
        let input_path = Path::new("plugin.esp.ghost");
1✔
669
        let resolved_path = resolve_path(&state, input_path);
1✔
670

1✔
671
        assert_eq!(data_path.join(input_path), resolved_path);
1✔
672

673
        let input_path = Path::new("file.txt");
1✔
674
        let resolved_path = resolve_path(&state, input_path);
1✔
675

1✔
676
        assert_eq!(data_path.join(input_path), resolved_path);
1✔
677
    }
1✔
678

679
    #[test]
680
    fn resolve_path_should_return_the_given_data_relative_path_plus_a_ghost_extension_if_the_plugin_path_does_not_exist(
1✔
681
    ) {
1✔
682
        let data_path = PathBuf::from(".");
1✔
683
        let state = State::new(GameType::Skyrim, data_path.clone());
1✔
684
        let input_path = Path::new("plugin.esp");
1✔
685
        let resolved_path = resolve_path(&state, input_path);
1✔
686

1✔
687
        assert_eq!(
1✔
688
            data_path.join(input_path.with_extension("esp.ghost")),
1✔
689
            resolved_path
1✔
690
        );
1✔
691
    }
1✔
692

693
    #[test]
694
    fn resolve_path_should_not_add_ghost_extension_for_openmw() {
1✔
695
        let data_path = PathBuf::from(".");
1✔
696
        let state = State::new(GameType::OpenMW, data_path.clone());
1✔
697
        let input_path = Path::new("plugin.esp");
1✔
698
        let resolved_path = resolve_path(&state, input_path);
1✔
699

1✔
700
        assert_eq!(data_path.join(input_path), resolved_path);
1✔
701
    }
1✔
702

703
    #[test]
704
    fn resolve_path_should_check_external_data_paths_in_order_before_data_path() {
1✔
705
        use std::fs::copy;
706
        use std::fs::create_dir;
707

708
        let tmp_dir = tempfile::tempdir().unwrap();
1✔
709
        let external_data_path_1 = tmp_dir.path().join("Data1");
1✔
710
        let external_data_path_2 = tmp_dir.path().join("Data2");
1✔
711
        let data_path = tmp_dir.path().join("Data3");
1✔
712

1✔
713
        create_dir(&external_data_path_1).unwrap();
1✔
714
        create_dir(&external_data_path_2).unwrap();
1✔
715
        create_dir(&data_path).unwrap();
1✔
716
        copy(
1✔
717
            Path::new("Cargo.toml"),
1✔
718
            external_data_path_1.join("Cargo.toml"),
1✔
719
        )
1✔
720
        .unwrap();
1✔
721
        copy(
1✔
722
            Path::new("Cargo.toml"),
1✔
723
            external_data_path_2.join("Cargo.toml"),
1✔
724
        )
1✔
725
        .unwrap();
1✔
726
        copy(Path::new("Cargo.toml"), data_path.join("Cargo.toml")).unwrap();
1✔
727

1✔
728
        let mut state = State::new(GameType::Skyrim, data_path);
1✔
729
        state.set_additional_data_paths(vec![
1✔
730
            external_data_path_1.clone(),
1✔
731
            external_data_path_2.clone(),
1✔
732
        ]);
1✔
733

1✔
734
        let input_path = Path::new("Cargo.toml");
1✔
735
        let resolved_path = resolve_path(&state, input_path);
1✔
736

1✔
737
        assert_eq!(external_data_path_1.join(input_path), resolved_path);
1✔
738
    }
1✔
739

740
    #[test]
741
    fn resolve_path_should_check_external_data_paths_in_reverse_order_before_data_path_for_openmw()
1✔
742
    {
1✔
743
        use std::fs::copy;
744
        use std::fs::create_dir;
745

746
        let tmp_dir = tempfile::tempdir().unwrap();
1✔
747
        let external_data_path_1 = tmp_dir.path().join("Data1");
1✔
748
        let external_data_path_2 = tmp_dir.path().join("Data2");
1✔
749
        let data_path = tmp_dir.path().join("Data3");
1✔
750

1✔
751
        create_dir(&external_data_path_1).unwrap();
1✔
752
        create_dir(&external_data_path_2).unwrap();
1✔
753
        create_dir(&data_path).unwrap();
1✔
754
        copy(
1✔
755
            Path::new("Cargo.toml"),
1✔
756
            external_data_path_1.join("Cargo.toml"),
1✔
757
        )
1✔
758
        .unwrap();
1✔
759
        copy(
1✔
760
            Path::new("Cargo.toml"),
1✔
761
            external_data_path_2.join("Cargo.toml"),
1✔
762
        )
1✔
763
        .unwrap();
1✔
764
        copy(Path::new("Cargo.toml"), data_path.join("Cargo.toml")).unwrap();
1✔
765

1✔
766
        let mut state = State::new(GameType::OpenMW, data_path);
1✔
767
        state.set_additional_data_paths(vec![
1✔
768
            external_data_path_1.clone(),
1✔
769
            external_data_path_2.clone(),
1✔
770
        ]);
1✔
771

1✔
772
        let input_path = Path::new("Cargo.toml");
1✔
773
        let resolved_path = resolve_path(&state, input_path);
1✔
774

1✔
775
        assert_eq!(external_data_path_2.join(input_path), resolved_path);
1✔
776
    }
1✔
777
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc