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

MeltyPlayer / MeltyTool / 20982513833

14 Jan 2026 04:35AM UTC coverage: 41.138% (-0.8%) from 41.907%
20982513833

push

github

MeltyPlayer
Fixed broken shader source tests.

6752 of 18485 branches covered (36.53%)

Branch coverage included in aggregate %.

28650 of 67572 relevant lines covered (42.4%)

64006.02 hits per line

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

24.08
/FinModelUtility/ImaginaryFileSystem/ImaginaryDirectory.cs
1
using System.Globalization;
2
using System.Text.RegularExpressions;
3

4
namespace System.IO.Abstractions.TestingHelpers;
5

6
using XFS = MockUnixSupport;
7

8
/// <inheritdoc />
9
#if FEATURE_SERIALIZABLE
10
[Serializable]
11
#endif
12
public class ImaginaryDirectory : DirectoryBase {
13
  private readonly IImaginaryFileDataAccessor imaginaryFileDataAccessor_;
14
  private string currentDirectory;
15

16
  /// <inheritdoc />
17
  public ImaginaryDirectory(IImaginaryFileDataAccessor imaginaryFileDataAccessor,
18
                       FileBase fileBase,
19
                       string currentDirectory) :
20
      this(imaginaryFileDataAccessor, currentDirectory) { }
×
21

22
  /// <inheritdoc />
23
  public ImaginaryDirectory(IImaginaryFileDataAccessor imaginaryFileDataAccessor,
24
                       string currentDirectory) : base(
20!
25
      imaginaryFileDataAccessor?.FileSystem) {
40✔
26
    this.currentDirectory = currentDirectory;
20✔
27
    this.imaginaryFileDataAccessor_ =
20!
28
        imaginaryFileDataAccessor ??
20✔
29
        throw new ArgumentNullException(nameof(imaginaryFileDataAccessor));
20✔
30
  }
20✔
31

32

33
  /// <inheritdoc />
34
  public override IDirectoryInfo CreateDirectory(string path) {
85✔
35
    return CreateDirectoryInternal(path);
85✔
36
  }
85✔
37

38
#if FEATURE_UNIX_FILE_MODE
39
        /// <inheritdoc />
40
        public override IDirectoryInfo CreateDirectory(string path, UnixFileMode unixCreateMode)
41
        {
×
42
            throw CommonExceptions.NotImplemented();
×
43
        }
44
#endif
45

46
  private IDirectoryInfo CreateDirectoryInternal(string path) {
85✔
47
    if (path == null) {
85!
48
      throw new ArgumentNullException(nameof(path));
×
49
    }
50

51
    if (path.Length == 0) {
85!
52
      throw new ArgumentException(
×
53
          StringResources.Manager.GetString(
×
54
              "PATH_CANNOT_BE_THE_EMPTY_STRING_OR_ALL_WHITESPACE"),
×
55
          "path");
×
56
    }
57

58
    if (this.imaginaryFileDataAccessor_.ImaginaryPathVerifier.HasIllegalCharacters(
85!
59
            path,
85✔
60
            true)) {
85✔
61
      throw CommonExceptions.IllegalCharactersInPath(nameof(path));
×
62
    }
63

64
    path = this.imaginaryFileDataAccessor_.Path.GetFullPath(path).TrimSlashes();
85✔
65
    if (ImaginaryUnixSupport.IsWindowsPlatform()) {
170✔
66
      path = path.TrimEnd(' ');
85✔
67
    }
85✔
68

69
    var existingFile = this.imaginaryFileDataAccessor_.GetFile(path);
85✔
70
    if (existingFile == null) {
170!
71
      this.imaginaryFileDataAccessor_.AddDirectory(path);
85✔
72
    } else if (!existingFile.IsDirectory) {
85!
73
      throw CommonExceptions.FileAlreadyExists("path");
×
74
    }
75

76
    var created = new ImaginaryDirectoryInfo(this.imaginaryFileDataAccessor_, path);
85✔
77

78
    return created;
85✔
79
  }
85✔
80

81
#if FEATURE_CREATE_SYMBOLIC_LINK
82
        /// <inheritdoc />
83
        public override IFileSystemInfo CreateSymbolicLink(string path, string pathToTarget)
84
        {
×
85
            imaginaryFileDataAccessor_.ImaginaryPathVerifier.IsLegalAbsoluteOrRelative(path, nameof(path));
×
86
            imaginaryFileDataAccessor_.ImaginaryPathVerifier.IsLegalAbsoluteOrRelative(pathToTarget, nameof(pathToTarget));
×
87

88
            if (Exists(path))
×
89
            {
×
90
                throw CommonExceptions.FileAlreadyExists(nameof(path));
×
91
            }
92

93
            imaginaryFileDataAccessor_.AddDirectory(path);
×
94
            imaginaryFileDataAccessor_.GetFile(path).LinkTarget = pathToTarget;
×
95

96
            var directoryInfo =
×
97
 new ImaginaryDirectoryInfo(imaginaryFileDataAccessor_, path);
×
98
            directoryInfo.Attributes |= FileAttributes.ReparsePoint;
×
99
            return directoryInfo;
×
100
        }
×
101
#endif
102

103
#if FEATURE_CREATE_TEMP_SUBDIRECTORY
104
        /// <inheritdoc />
105
        public override IDirectoryInfo CreateTempSubdirectory(string prefix =
106
 null)
107
        {
×
108
            prefix ??= "";
×
109
            string potentialTempDirectory;
110

111
            // Perform directory name generation in a loop, just in case the randomly generated name already exists.
112
            do
113
            {
×
114
                var randomDir =
×
115
 $"{prefix}{FileSystem.Path.GetRandomFileName()}";
×
116
                potentialTempDirectory =
×
117
 Path.Combine(FileSystem.Path.GetTempPath(), randomDir);
×
118
            } while (Exists(potentialTempDirectory));
×
119

120
            return CreateDirectoryInternal(potentialTempDirectory);
×
121
        }
×
122
#endif
123

124
  /// <inheritdoc />
125
  public override void Delete(string path) {
×
126
    Delete(path, false);
×
127
  }
×
128

129

130
  /// <inheritdoc />
131
  public override void Delete(string path, bool recursive) {
85✔
132
    path = this.imaginaryFileDataAccessor_.Path.GetFullPath(path).TrimSlashes();
85✔
133

134
    var stringOps = this.imaginaryFileDataAccessor_.StringOperations;
85✔
135
    var pathWithDirectorySeparatorChar = $"{path}{Path.DirectorySeparatorChar}";
85✔
136

137
    var affectedPaths = this.imaginaryFileDataAccessor_
85✔
138
                            .AllPaths
85✔
139
                            .Where(p => stringOps.Equals(p, path) ||
5,922✔
140
                                        stringOps.StartsWith(
5,922✔
141
                                            p,
5,922✔
142
                                            pathWithDirectorySeparatorChar))
5,922✔
143
                            .ToList();
85✔
144

145
    if (!affectedPaths.Any()) {
85!
146
      throw CommonExceptions.PathDoesNotExistOrCouldNotBeFound(path);
×
147
    }
148

149
    if (!recursive && affectedPaths.Count > 1) {
85!
150
      throw new IOException("The directory specified by " +
×
151
                            path +
×
152
                            " is read-only, or recursive is false and " +
×
153
                            path +
×
154
                            " is not an empty directory.");
×
155
    }
156

157
    bool isFile = !this.imaginaryFileDataAccessor_.GetFile(path).IsDirectory;
85✔
158
    if (isFile) {
85!
159
      throw new IOException("The directory name is invalid.");
×
160
    }
161

162
    foreach (var affectedPath in affectedPaths) {
17,505✔
163
      this.imaginaryFileDataAccessor_.RemoveFile(affectedPath);
5,750✔
164
    }
5,750✔
165
  }
85✔
166

167

168
  /// <inheritdoc />
169
  public override bool Exists(string path) {
11,670✔
170
    if (path == "/") {
11,670!
171
      return true;
×
172
    }
173

174
    try {
11,670✔
175
      path = path.TrimSlashes();
11,670✔
176
      path = this.imaginaryFileDataAccessor_.Path.GetFullPath(path);
11,670✔
177
      return this.imaginaryFileDataAccessor_.GetFile(path)?.IsDirectory ??
11,670!
178
             false;
11,670✔
179
    } catch (Exception) {
×
180
      return false;
×
181
    }
182
  }
11,670✔
183

184

185
  /// <inheritdoc />
186
  public override DateTime GetCreationTime(string path) {
×
187
    return this.imaginaryFileDataAccessor_.File.GetCreationTime(path);
×
188
  }
×
189

190

191
  /// <inheritdoc />
192
  public override DateTime GetCreationTimeUtc(string path) {
×
193
    return this.imaginaryFileDataAccessor_.File.GetCreationTimeUtc(path);
×
194
  }
×
195

196
  /// <inheritdoc />
197
  public override string GetCurrentDirectory() {
143,799✔
198
    return currentDirectory;
143,799✔
199
  }
143,799✔
200

201
  /// <inheritdoc />
202
  public override string[] GetDirectories(string path) {
×
203
    return GetDirectories(path, "*");
×
204
  }
×
205

206
  /// <inheritdoc />
207
  public override string[] GetDirectories(string path, string searchPattern) {
×
208
    return GetDirectories(path, searchPattern, SearchOption.TopDirectoryOnly);
×
209
  }
×
210

211
  /// <inheritdoc />
212
  public override string[] GetDirectories(string path,
213
                                          string searchPattern,
214
                                          SearchOption searchOption) {
×
215
    return EnumerateDirectories(path, searchPattern, searchOption).ToArray();
×
216
  }
×
217

218
#if FEATURE_ENUMERATION_OPTIONS
219
        /// <inheritdoc />
220
        public override string[] GetDirectories(string path, string searchPattern,
221
            EnumerationOptions enumerationOptions)
222
        {
×
223
            return GetDirectories(path, "*", EnumerationOptionsToSearchOption(enumerationOptions));
×
224
        }
×
225
#endif
226

227
  /// <inheritdoc />
228
  public override string GetDirectoryRoot(string path) {
×
229
    return Path.GetPathRoot(path);
×
230
  }
×
231

232
  /// <inheritdoc />
233
  public override string[] GetFiles(string path) {
170✔
234
    // Same as what the real framework does
235
    return GetFiles(path, "*");
170✔
236
  }
170✔
237

238
  /// <inheritdoc />
239
  public override string[] GetFiles(string path, string searchPattern) {
170✔
240
    // Same as what the real framework does
241
    return GetFiles(path, searchPattern, SearchOption.TopDirectoryOnly);
170✔
242
  }
170✔
243

244
  /// <inheritdoc />
245
  public override string[] GetFiles(string path,
246
                                    string searchPattern,
247
                                    SearchOption searchOption) {
170✔
248
    return GetFilesInternal(this.imaginaryFileDataAccessor_.AllFiles,
170✔
249
                            path,
170✔
250
                            searchPattern,
170✔
251
                            searchOption);
170✔
252
  }
170✔
253

254
#if FEATURE_ENUMERATION_OPTIONS
255
        /// <inheritdoc />
256
        public override string[] GetFiles(string path, string searchPattern, EnumerationOptions enumerationOptions)
257
        {
×
258
            return GetFiles(path, searchPattern, EnumerationOptionsToSearchOption(enumerationOptions));
×
259
        }
×
260
#endif
261

262
  private string[] GetFilesInternal(
263
      IEnumerable<string> files,
264
      string path,
265
      string searchPattern,
266
      SearchOption searchOption) {
170✔
267
    if (path == null) {
170!
268
      throw new ArgumentNullException(nameof(path));
×
269
    }
270

271
    if (path.Any(c => Path.GetInvalidPathChars().Contains(c))) {
7,650!
272
      throw new ArgumentException("Invalid character(s) in path", nameof(path));
×
273
    }
274

275
    CheckSearchPattern(searchPattern);
170✔
276
    if (searchPattern.Equals(string.Empty,
170!
277
                             StringComparison.OrdinalIgnoreCase)) {
170✔
278
      searchPattern = "*";
×
279
    }
×
280

281
    path = path.TrimSlashes();
170✔
282
    path = path.NormalizeSlashes();
170✔
283
    path = this.imaginaryFileDataAccessor_.Path.GetFullPath(path);
170✔
284

285
    if (!Exists(path)) {
170!
286
      throw CommonExceptions.CouldNotFindPartOfPath(path);
×
287
    }
288

289
    if (!path.EndsWith(Path.DirectorySeparatorChar.ToString())) {
340✔
290
      path += Path.DirectorySeparatorChar;
170✔
291
    }
170✔
292

293
    var isUnix = ImaginaryUnixSupport.IsUnixPlatform();
170✔
294

295
    var allDirectoriesPattern = isUnix
170!
296
        ? @"([^<>:""/|?*]*/)*"
170✔
297
        : @"([^<>:""/\\|?*]*\\)*";
170✔
298

299
    var searchEndInStarDot = searchPattern.EndsWith(@"*.");
170✔
300

301
    string fileNamePattern;
302
    string pathPatternNoExtension = string.Empty;
170✔
303
    string pathPatternEndsInDot = string.Empty;
170✔
304
    string pathPatternSpecial = null;
170✔
305

306
    if (searchPattern == "*") {
340!
307
      fileNamePattern = isUnix ? @"[^/]*?/?" : @"[^\\]*?\\?";
170!
308
    } else {
170✔
309
      fileNamePattern = Regex.Escape(searchPattern)
×
310
                             .Replace(@"\*",
×
311
                                      isUnix
×
312
                                          ? @"[^<>:""/|?*]*?"
×
313
                                          : @"[^<>:""/\\|?*]*?")
×
314
                             .Replace(@"\?",
×
315
                                      isUnix
×
316
                                          ? @"[^<>:""/|?*]?"
×
317
                                          : @"[^<>:""/\\|?*]?");
×
318

319
      var extension = Path.GetExtension(searchPattern);
×
320
      bool hasExtensionLengthOfThree = extension != null &&
×
321
                                       extension.Length == 4 &&
×
322
                                       !extension.Contains("*") &&
×
323
                                       !extension.Contains("?");
×
324
      if (hasExtensionLengthOfThree) {
×
325
        var fileNamePatternSpecial =
×
326
            string.Format(CultureInfo.InvariantCulture,
×
327
                          "{0}[^.]",
×
328
                          fileNamePattern);
×
329
        pathPatternSpecial = string.Format(
×
330
            CultureInfo.InvariantCulture,
×
331
            isUnix ? @"(?i:^{0}{1}{2}(?:/?)$)" : @"(?i:^{0}{1}{2}(?:\\?)$)",
×
332
            Regex.Escape(path),
×
333
            searchOption == SearchOption.AllDirectories
×
334
                ? allDirectoriesPattern
×
335
                : string.Empty,
×
336
            fileNamePatternSpecial);
×
337
      }
×
338
    }
×
339

340
    var pathPattern = string.Format(
170!
341
        CultureInfo.InvariantCulture,
170✔
342
        isUnix ? @"(?i:^{0}{1}{2}(?:/?)$)" : @"(?i:^{0}{1}{2}(?:\\?)$)",
170✔
343
        Regex.Escape(path),
170✔
344
        searchOption == SearchOption.AllDirectories
170✔
345
            ? allDirectoriesPattern
170✔
346
            : string.Empty,
170✔
347
        fileNamePattern);
170✔
348

349
    if (searchEndInStarDot) {
170!
350
      pathPatternNoExtension
×
351
          = ReplaceLastOccurrence(pathPattern, @"]*?\.", @"\.]*?[.]*");
×
352
      pathPatternEndsInDot
×
353
          = ReplaceLastOccurrence(pathPattern, @"]*?\.", @"]*?[.]{1,}");
×
354
    }
×
355

356
    return files.Where(p =>
170✔
357
                           !searchEndInStarDot
7,576!
358
                               ? (Regex.IsMatch(p, pathPattern) ||
7,576✔
359
                                  (pathPatternSpecial != null &&
7,576✔
360
                                   Regex.IsMatch(p, pathPatternSpecial)))
7,576✔
361
                               : (Regex.IsMatch(p, pathPatternNoExtension) ||
7,576✔
362
                                  Regex.IsMatch(p, pathPatternEndsInDot))
7,576✔
363
                )
170✔
364
                .ToArray();
170✔
365
  }
170✔
366

367
  /// <inheritdoc />
368
  public override string[] GetFileSystemEntries(string path) {
×
369
    return GetFileSystemEntries(path, "*");
×
370
  }
×
371

372
  /// <inheritdoc />
373
  public override string[] GetFileSystemEntries(
374
      string path,
375
      string searchPattern) {
×
376
    var dirs = GetDirectories(path, searchPattern);
×
377
    var files = GetFiles(path, searchPattern);
×
378

379
    return dirs.Union(files).ToArray();
×
380
  }
×
381

382
  /// <inheritdoc />
383
  public override string[] GetFileSystemEntries(
384
      string path,
385
      string searchPattern,
386
      SearchOption searchOption) {
×
387
    var dirs = GetDirectories(path, searchPattern, searchOption);
×
388
    var files = GetFiles(path, searchPattern, searchOption);
×
389

390
    return dirs.Union(files).ToArray();
×
391
  }
×
392

393
#if FEATURE_ENUMERATION_OPTIONS
394
        /// <inheritdoc />
395
        public override string[] GetFileSystemEntries(string path, string searchPattern,
396
            EnumerationOptions enumerationOptions)
397
        {
×
398
            return GetFileSystemEntries(path, "*", EnumerationOptionsToSearchOption(enumerationOptions));
×
399
        }
×
400
#endif
401

402
  /// <inheritdoc />
403
  public override DateTime GetLastAccessTime(string path) {
×
404
    return this.imaginaryFileDataAccessor_.File.GetLastAccessTime(path);
×
405
  }
×
406

407
  /// <inheritdoc />
408
  public override DateTime GetLastAccessTimeUtc(string path) {
×
409
    return this.imaginaryFileDataAccessor_.File.GetLastAccessTimeUtc(path);
×
410
  }
×
411

412
  /// <inheritdoc />
413
  public override DateTime GetLastWriteTime(string path) {
×
414
    return this.imaginaryFileDataAccessor_.File.GetLastWriteTime(path);
×
415
  }
×
416

417
  /// <inheritdoc />
418
  public override DateTime GetLastWriteTimeUtc(string path) {
×
419
    return this.imaginaryFileDataAccessor_.File.GetLastWriteTimeUtc(path);
×
420
  }
×
421

422
  /// <inheritdoc />
423
  public override string[] GetLogicalDrives() {
×
424
    return this.imaginaryFileDataAccessor_
×
425
               .AllDirectories
×
426
               .Select(d => new ImaginaryDirectoryInfo(
×
427
                           this.imaginaryFileDataAccessor_,
×
428
                           d).Root.FullName)
×
429
               .Select(r => this.imaginaryFileDataAccessor_.StringOperations
×
430
                                .ToUpper(r))
×
431
               .Distinct()
×
432
               .ToArray();
×
433
  }
×
434

435
  /// <inheritdoc />
436
  public override IDirectoryInfo GetParent(string path) {
×
437
    if (path == null) {
×
438
      throw new ArgumentNullException(nameof(path));
×
439
    }
440

441
    if (path.Length == 0) {
×
442
      throw new ArgumentException(
×
443
          StringResources.Manager.GetString(
×
444
              "PATH_CANNOT_BE_THE_EMPTY_STRING_OR_ALL_WHITESPACE"),
×
445
          "path");
×
446
    }
447

448
    if (this.imaginaryFileDataAccessor_.ImaginaryPathVerifier.HasIllegalCharacters(
×
449
            path,
×
450
            false)) {
×
451
      throw new ArgumentException("Path contains invalid path characters.",
×
452
                                  "path");
×
453
    }
454

455
    var absolutePath = this.imaginaryFileDataAccessor_.Path.GetFullPath(path);
×
456
    var sepAsString = this.imaginaryFileDataAccessor_.Path
×
457
                          .DirectorySeparatorChar.ToString();
×
458
    var lastIndex = 0;
×
459

460
    if (absolutePath != sepAsString) {
×
461
      var startIndex
×
462
          = this.imaginaryFileDataAccessor_.StringOperations.EndsWith(
×
463
              absolutePath,
×
464
              sepAsString)
×
465
              ? absolutePath.Length - 1
×
466
              : absolutePath.Length;
×
467
      lastIndex = absolutePath.LastIndexOf(
×
468
          this.imaginaryFileDataAccessor_.Path.DirectorySeparatorChar,
×
469
          startIndex - 1);
×
470

471
      if (lastIndex < 0) {
×
472
        return null;
×
473
      }
474
    }
×
475

476
    var parentPath = absolutePath.Substring(0, lastIndex);
×
477

478
    if (string.IsNullOrEmpty(parentPath)) {
×
479
      // On the Unix platform, the parent of a path consisting of a slash followed by
480
      // non-slashes is the root, '/'.
481
      if (ImaginaryUnixSupport.IsUnixPlatform()) {
×
482
        absolutePath = absolutePath.TrimSlashes();
×
483

484
        if (absolutePath.Length > 1 &&
×
485
            absolutePath.LastIndexOf(this.imaginaryFileDataAccessor_.Path
×
486
                                         .DirectorySeparatorChar) ==
×
487
            0) {
×
488
          return new ImaginaryDirectoryInfo(this.imaginaryFileDataAccessor_,
×
489
                                       this.imaginaryFileDataAccessor_.Path
×
490
                                           .DirectorySeparatorChar.ToString());
×
491
        }
492
      }
×
493

494
      return null;
×
495
    }
496

497
    return new ImaginaryDirectoryInfo(this.imaginaryFileDataAccessor_, parentPath);
×
498
  }
×
499

500
  /// <inheritdoc />
501
  public override void Move(string sourceDirName, string destDirName) {
×
502
    var fullSourcePath = this.imaginaryFileDataAccessor_.Path
×
503
                             .GetFullPath(sourceDirName)
×
504
                             .TrimSlashes();
×
505
    var fullDestPath = this.imaginaryFileDataAccessor_.Path
×
506
                           .GetFullPath(destDirName)
×
507
                           .TrimSlashes();
×
508

509
    if (string.Equals(fullSourcePath, fullDestPath, StringComparison.Ordinal)) {
×
510
      throw new IOException("Source and destination path must be different.");
×
511
    }
512

513
    //if we're moving a file, not a directory, call the appropriate file moving function.
514
    var fileData = this.imaginaryFileDataAccessor_.GetFile(fullSourcePath);
×
515
    if (fileData?.Attributes.HasFlag(FileAttributes.Directory) == false) {
×
516
      this.imaginaryFileDataAccessor_.File.Move(fullSourcePath, fullDestPath);
×
517
      return;
×
518
    }
519

520
    var sourceRoot
×
521
        = this.imaginaryFileDataAccessor_.Path.GetPathRoot(fullSourcePath);
×
522
    var destinationRoot
×
523
        = this.imaginaryFileDataAccessor_.Path.GetPathRoot(fullDestPath);
×
524

525
    if (!this.imaginaryFileDataAccessor_.StringOperations.Equals(
×
526
            sourceRoot,
×
527
            destinationRoot)) {
×
528
      throw new IOException(
×
529
          "Source and destination path must have identical roots. Move will not work across volumes.");
×
530
    }
531

532
    if (!this.imaginaryFileDataAccessor_.Directory.Exists(fullSourcePath)) {
×
533
      throw CommonExceptions.CouldNotFindPartOfPath(sourceDirName);
×
534
    }
535

536
    if (!this.imaginaryFileDataAccessor_.Directory.GetParent(fullDestPath)
×
537
             .Exists) {
×
538
      throw CommonExceptions.CouldNotFindPartOfPath(destDirName);
×
539
    }
540

541
    if (this.imaginaryFileDataAccessor_.Directory.Exists(fullDestPath) ||
×
542
        this.imaginaryFileDataAccessor_.File.Exists(fullDestPath)) {
×
543
      // In Windows, file/dir names are case sensetive, C:\\temp\\src and C:\\temp\\SRC and treated different
544
      if (ImaginaryUnixSupport.IsUnixPlatform() ||
×
545
          !string.Equals(fullSourcePath,
×
546
                         fullDestPath,
×
547
                         StringComparison.OrdinalIgnoreCase)) {
×
548
        throw CommonExceptions.CannotCreateBecauseSameNameAlreadyExists(
×
549
            fullDestPath);
×
550
      }
551
    }
×
552

553
    this.imaginaryFileDataAccessor_.MoveDirectory(fullSourcePath, fullDestPath);
×
554
  }
×
555

556
#if FEATURE_CREATE_SYMBOLIC_LINK
557
        /// <inheritdoc />
558
        public override IFileSystemInfo ResolveLinkTarget(string linkPath, bool returnFinalTarget)
559
        {
×
560
            var initialContainer = imaginaryFileDataAccessor_.GetFile(linkPath);
×
561
            if (initialContainer.LinkTarget != null)
×
562
            {
×
563
                var nextLocation = initialContainer.LinkTarget;
×
564
                var nextContainer =
×
565
 imaginaryFileDataAccessor_.GetFile(nextLocation);
×
566

567
                if (returnFinalTarget)
×
568
                {
×
569
                    // The maximum number of symbolic links that are followed:
570
                    // https://learn.microsoft.com/en-us/dotnet/api/system.io.directory.resolvelinktarget?view=net-6.0#remarks
571
                    int maxResolveLinks = XFS.IsWindowsPlatform() ? 63 : 40;
×
572
                    for (int i = 1; i < maxResolveLinks; i++)
×
573
                    {
×
574
                        if (nextContainer.LinkTarget == null)
×
575
                        {
×
576
                            break;
×
577
                        }
578
                        nextLocation = nextContainer.LinkTarget;
×
579
                        nextContainer =
×
580
 imaginaryFileDataAccessor_.GetFile(nextLocation);
×
581
                    }
×
582

583
                    if (nextContainer.LinkTarget != null)
×
584
                    {
×
585
                        throw CommonExceptions.NameCannotBeResolvedByTheSystem(linkPath);
×
586
                    }
587
                }
×
588

589
                if (nextContainer.IsDirectory)
×
590
                {
×
591
                    return new ImaginaryDirectoryInfo(imaginaryFileDataAccessor_, nextLocation);
×
592
                }
593
                else
594
                {
×
595
                    return new ImaginaryFileInfo(imaginaryFileDataAccessor_, nextLocation);
×
596
                }
597
            }
598
            throw CommonExceptions.NameCannotBeResolvedByTheSystem(linkPath);
×
599
        }
×
600

601
#endif
602

603
  /// <inheritdoc />
604
  public override void SetCreationTime(string path, DateTime creationTime) {
×
605
    this.imaginaryFileDataAccessor_.File.SetCreationTime(path, creationTime);
×
606
  }
×
607

608
  /// <inheritdoc />
609
  public override void
610
      SetCreationTimeUtc(string path, DateTime creationTimeUtc) {
×
611
    this.imaginaryFileDataAccessor_.File.SetCreationTimeUtc(
×
612
        path,
×
613
        creationTimeUtc);
×
614
  }
×
615

616
  /// <inheritdoc />
617
  public override void SetCurrentDirectory(string path) {
×
618
    currentDirectory = this.imaginaryFileDataAccessor_.Path.GetFullPath(path);
×
619
  }
×
620

621
  /// <inheritdoc />
622
  public override void SetLastAccessTime(string path, DateTime lastAccessTime) {
×
623
    this.imaginaryFileDataAccessor_.File
×
624
        .SetLastAccessTime(path, lastAccessTime);
×
625
  }
×
626

627
  /// <inheritdoc />
628
  public override void SetLastAccessTimeUtc(string path,
629
                                            DateTime lastAccessTimeUtc) {
×
630
    this.imaginaryFileDataAccessor_.File.SetLastAccessTimeUtc(
×
631
        path,
×
632
        lastAccessTimeUtc);
×
633
  }
×
634

635
  /// <inheritdoc />
636
  public override void SetLastWriteTime(string path, DateTime lastWriteTime) {
×
637
    this.imaginaryFileDataAccessor_.File.SetLastWriteTime(path, lastWriteTime);
×
638
  }
×
639

640
  /// <inheritdoc />
641
  public override void SetLastWriteTimeUtc(string path,
642
                                           DateTime lastWriteTimeUtc) {
×
643
    this.imaginaryFileDataAccessor_.File.SetLastWriteTimeUtc(
×
644
        path,
×
645
        lastWriteTimeUtc);
×
646
  }
×
647

648
  /// <inheritdoc />
649
  public override IEnumerable<string> EnumerateDirectories(string path) {
×
650
    return EnumerateDirectories(path, "*");
×
651
  }
×
652

653
  /// <inheritdoc />
654
  public override IEnumerable<string> EnumerateDirectories(
655
      string path,
656
      string searchPattern) {
×
657
    return EnumerateDirectories(path,
×
658
                                searchPattern,
×
659
                                SearchOption.TopDirectoryOnly);
×
660
  }
×
661

662
  /// <inheritdoc />
663
  public override IEnumerable<string> EnumerateDirectories(
664
      string path,
665
      string searchPattern,
666
      SearchOption searchOption) {
×
667
    this.imaginaryFileDataAccessor_.ImaginaryPathVerifier.IsLegalAbsoluteOrRelative(
×
668
        path,
×
669
        "path");
×
670
    var originalPath = path;
×
671
    path = path.TrimSlashes();
×
672
    path = this.imaginaryFileDataAccessor_.Path.GetFullPath(path);
×
673
    return GetFilesInternal(this.imaginaryFileDataAccessor_.AllDirectories,
×
674
                            path,
×
675
                            searchPattern,
×
676
                            searchOption)
×
677
           .Where(p => !this.imaginaryFileDataAccessor_.StringOperations.Equals(
×
678
                      p,
×
679
                      path))
×
680
           .Select(p => FixPrefix(p, originalPath));
×
681
  }
×
682

683
  private string FixPrefix(string path, string originalPath) {
×
684
    var normalizedOriginalPath
×
685
        = this.imaginaryFileDataAccessor_.Path.GetFullPath(originalPath);
×
686
    var pathWithoutOriginalPath = path.Substring(normalizedOriginalPath.Length)
×
687
                                      .TrimStart(
×
688
                                          this.imaginaryFileDataAccessor_.Path
×
689
                                              .DirectorySeparatorChar);
×
690
    return this.imaginaryFileDataAccessor_.Path.Combine(
×
691
        originalPath,
×
692
        pathWithoutOriginalPath);
×
693
  }
×
694

695
#if FEATURE_ENUMERATION_OPTIONS
696
        /// <inheritdoc />
697
        public override IEnumerable<string> EnumerateDirectories(string path, string searchPattern, EnumerationOptions enumerationOptions)
698
        {
×
699
            var searchOption =
×
700
 enumerationOptions.RecurseSubdirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
×
701
            return EnumerateDirectories(path, searchPattern, searchOption);
×
702
        }
×
703
#endif
704

705
  /// <inheritdoc />
706
  public override IEnumerable<string> EnumerateFiles(string path) {
85✔
707
    return GetFiles(path);
85✔
708
  }
85✔
709

710
  /// <inheritdoc />
711
  public override IEnumerable<string> EnumerateFiles(
712
      string path,
713
      string searchPattern) {
×
714
    return GetFiles(path, searchPattern);
×
715
  }
×
716

717
  /// <inheritdoc />
718
  public override IEnumerable<string> EnumerateFiles(
719
      string path,
720
      string searchPattern,
721
      SearchOption searchOption) {
×
722
    return GetFiles(path, searchPattern, searchOption);
×
723
  }
×
724

725
#if FEATURE_ENUMERATION_OPTIONS
726
        /// <inheritdoc />
727
        public override IEnumerable<string> EnumerateFiles(string path, string searchPattern, EnumerationOptions enumerationOptions)
728
        {
×
729
            var searchOption =
×
730
 enumerationOptions.RecurseSubdirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
×
731
            return GetFiles(path, searchPattern, searchOption);
×
732
        }
×
733
#endif
734

735
  /// <inheritdoc />
736
  public override IEnumerable<string> EnumerateFileSystemEntries(string path) {
×
737
    return GetFileSystemEntries(path);
×
738
  }
×
739

740
  /// <inheritdoc />
741
  public override IEnumerable<string> EnumerateFileSystemEntries(
742
      string path,
743
      string searchPattern) {
×
744
    return GetFileSystemEntries(path, searchPattern);
×
745
  }
×
746

747
  /// <inheritdoc />
748
  public override IEnumerable<string> EnumerateFileSystemEntries(
749
      string path,
750
      string searchPattern,
751
      SearchOption searchOption) {
×
752
    return GetFileSystemEntries(path, searchPattern, searchOption);
×
753
  }
×
754

755
#if FEATURE_ENUMERATION_OPTIONS
756
        /// <inheritdoc />
757
        public override IEnumerable<string> EnumerateFileSystemEntries(string path, string searchPattern, EnumerationOptions enumerationOptions)
758
        {
×
759
            var searchOption =
×
760
 enumerationOptions.RecurseSubdirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
×
761
            var fileSystemEntries =
×
762
 new List<string>(GetFiles(path, searchPattern, searchOption));
×
763
            fileSystemEntries.AddRange(GetDirectories(path, searchPattern, searchOption));
×
764
            return fileSystemEntries;
×
765
        }
×
766
#endif
767

768
  private string EnsureAbsolutePath(string path) {
×
769
    return Path.IsPathRooted(path)
×
770
        ? path
×
771
        : Path.Combine(GetCurrentDirectory(), path);
×
772
  }
×
773

774
  private void CheckSearchPattern(string searchPattern) {
170✔
775
    if (searchPattern == null) {
170!
776
      throw new ArgumentNullException(nameof(searchPattern));
×
777
    }
778

779
    const string TWO_DOTS = "..";
780
    Func<ArgumentException> createException = ()
170✔
781
        => new ArgumentException(
170✔
782
            @"Search pattern cannot contain "".."" to move up directories and can be contained only internally in file/directory names, as in ""a..b"".",
170✔
783
            searchPattern);
170✔
784

785
    if (this.imaginaryFileDataAccessor_.StringOperations.EndsWith(
170!
786
            searchPattern,
170✔
787
            TWO_DOTS)) {
170✔
788
      throw createException();
×
789
    }
790

791
    var position
170✔
792
        = this.imaginaryFileDataAccessor_.StringOperations.IndexOf(
170✔
793
            searchPattern,
170✔
794
            TWO_DOTS);
170✔
795

796
    if (position >= 0) {
170!
797
      var characterAfterTwoDots = searchPattern[position + 2];
×
798

799
      if (characterAfterTwoDots == Path.DirectorySeparatorChar ||
×
800
          characterAfterTwoDots == Path.AltDirectorySeparatorChar) {
×
801
        throw createException();
×
802
      }
803
    }
×
804

805
    var invalidPathChars = Path.GetInvalidPathChars();
170✔
806
    if (searchPattern.IndexOfAny(invalidPathChars) > -1) {
170!
807
      throw CommonExceptions.IllegalCharactersInPath(nameof(searchPattern));
×
808
    }
809
  }
170✔
810

811
  private string ReplaceLastOccurrence(string source,
812
                                       string find,
813
                                       string replace) {
×
814
    if (source == null) {
×
815
      return source;
×
816
    }
817

818
    var place = source.LastIndexOf(find);
×
819

820
    if (place == -1) {
×
821
      return source;
×
822
    }
823

824
    var result = source.Remove(place, find.Length).Insert(place, replace);
×
825
    return result;
×
826
  }
×
827

828
#if FEATURE_ENUMERATION_OPTIONS
829
        private SearchOption EnumerationOptionsToSearchOption(EnumerationOptions enumerationOptions)
830
        {
×
831
            static Exception CreateExceptionForUnsupportedProperty(string propertyName)
832
            {
×
833
                return new NotSupportedException(
×
834
                    $"Changing EnumerationOptions.{propertyName} is not yet implemented for the mock file system."
×
835
                );
×
836
            }
×
837

838
            if (enumerationOptions.AttributesToSkip != (FileAttributes.System | FileAttributes.Hidden))
×
839
            {
×
840
                throw CreateExceptionForUnsupportedProperty("AttributesToSkip");
×
841
            }
842
            if (!enumerationOptions.IgnoreInaccessible)
×
843
            {
×
844
                throw CreateExceptionForUnsupportedProperty("IgnoreInaccessible");
×
845
            }
846
            if (enumerationOptions.MatchCasing != MatchCasing.PlatformDefault)
×
847
            {
×
848
                throw CreateExceptionForUnsupportedProperty("MatchCasing");
×
849
            }
850
            if (enumerationOptions.MatchType != MatchType.Simple)
×
851
            {
×
852
                throw CreateExceptionForUnsupportedProperty("MatchType");
×
853
            }
854
            if (enumerationOptions.ReturnSpecialDirectories)
×
855
            {
×
856
                throw CreateExceptionForUnsupportedProperty("ReturnSpecialDirectories");
×
857
            }
858

859
            return enumerationOptions.RecurseSubdirectories
×
860
                ? SearchOption.AllDirectories
×
861
                : SearchOption.TopDirectoryOnly;
×
862
        }
×
863
#endif
864
}
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