public ValidationResult ValidateInstallation()

in JetBrains.SbomUtils/src/JetBrains.SbomUtils/SbomValidator.cs [23:87]


    public ValidationResult ValidateInstallation(SbomModel sbomModel, IInstalledSoftwareProvider installedSoftwareProvider, ICollection<string> rootPackageNames, ICollection<string> exceptions, ValidationOptions? validationOptions = null)
    {
      if (sbomModel == null)
        throw new InvalidOperationException("Load an spdx document first");

      validationOptions ??= new ValidationOptions();

      ICollection<Package> productPackages;

      if (rootPackageNames.Any())
      {
        var rootPackages = _sbomOperations.FindRootPackageByName(sbomModel, rootPackageNames);
        if (!rootPackages.Any()) throw new InvalidOperationException($"None of root packages {string.Join(", ", rootPackageNames)} wasn't found in the SBOM");

        _logger.LogDebug("Found {count} root packages in the SBOM: {packages}", rootPackages.Count(), string.Join(", ", rootPackages.Select(p => p.Name)));

        productPackages = _sbomOperations.GetAllDependantPackages(sbomModel, rootPackages);
      }
      else
      {
        productPackages = sbomModel.Packages.Values;
      }

      _logger.LogDebug("{count} dependent packages were collected", productPackages.Count);

      var packagesHashSet = productPackages.ToHashSet();
      var (installationFiles, ignoredFiles) = installedSoftwareProvider.GetFiles(exceptions);

      ConcurrentBag<MissingFile> missingFiles = new ConcurrentBag<MissingFile>();
      ConcurrentBag<FileVerificationResult> fileVerificationResults = new ConcurrentBag<FileVerificationResult>();

      ParallelOptions parallelOptions = new ParallelOptions()
      {
        MaxDegreeOfParallelism = validationOptions.Threads,
      };

      Parallel.ForEach(installationFiles, parallelOptions, (installationFile, token) =>
      {
        if (sbomModel.FilesDictionaryByRelativePath.TryGetValue(installationFile, out var sbomFiles))
        {
          var fileValidationResult = ValidateFile(installedSoftwareProvider, installationFile, sbomFiles, packagesHashSet);

          fileVerificationResults.Add(fileValidationResult);
        }
        else
        {
          var fileName = Path.GetFileName(installationFile);

          if (sbomModel.FilesDictionaryByFileName.TryGetValue(fileName, out var filesFromAnotherPackages))
            missingFiles.Add(new MissingFile(installationFile, filesFromAnotherPackages));
          else
            missingFiles.Add(new MissingFile(installationFile, Array.Empty<FileInfo>()));
        }
      });

      var validationResult = new ValidationResult(
        success: !(missingFiles.Any() || fileVerificationResults.Any(f => !f.Success)),
        errorMessage: null,
        filesChecked: installationFiles.Count,
        ignoredFiles: ignoredFiles.ToArray(),
        filesMissingInSbom: missingFiles.ToArray(),
        fileVerificationResults: fileVerificationResults.ToArray());

      return validationResult;
    }