Add sourcelink tests (#17309)
Co-authored-by: Matt Thalman <mthalman@microsoft.com>
This commit is contained in:
parent
c9b48273d9
commit
9a21558447
4 changed files with 156 additions and 2 deletions
|
@ -17,10 +17,14 @@ internal static class ExecuteHelper
|
|||
string args,
|
||||
ITestOutputHelper outputHelper,
|
||||
bool logOutput = false,
|
||||
bool excludeInfo = false,
|
||||
Action<Process>? configureCallback = null,
|
||||
int millisecondTimeout = -1)
|
||||
{
|
||||
outputHelper.WriteLine($"Executing: {fileName} {args}");
|
||||
if (!excludeInfo)
|
||||
{
|
||||
outputHelper.WriteLine($"Executing: {fileName} {args}");
|
||||
}
|
||||
|
||||
Process process = new()
|
||||
{
|
||||
|
|
|
@ -21,7 +21,7 @@ public class OmniSharpTests : SmokeTests
|
|||
// Update version as new releases become available: https://github.com/OmniSharp/omnisharp-roslyn/releases
|
||||
private const string OmniSharpReleaseVersion = "1.39.8";
|
||||
|
||||
private string OmniSharpDirectory { get; } = Path.Combine(Directory.GetCurrentDirectory(), "omnisharp");
|
||||
private string OmniSharpDirectory { get; } = Path.Combine(Directory.GetCurrentDirectory(), nameof(OmniSharpTests));
|
||||
|
||||
public OmniSharpTests(ITestOutputHelper outputHelper) : base(outputHelper) { }
|
||||
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.DotNet.SourceBuild.SmokeTests;
|
||||
|
||||
public class SourcelinkTests : SmokeTests
|
||||
{
|
||||
private static string SourcelinkRoot { get; } = Path.Combine(Directory.GetCurrentDirectory(), nameof(SourcelinkTests));
|
||||
|
||||
public SourcelinkTests(ITestOutputHelper outputHelper) : base(outputHelper) { }
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that all symbols have valid sourcelinks.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void VerifySourcelinks()
|
||||
{
|
||||
if (Directory.Exists(SourcelinkRoot))
|
||||
{
|
||||
Directory.Delete(SourcelinkRoot, true);
|
||||
}
|
||||
Directory.CreateDirectory(SourcelinkRoot);
|
||||
|
||||
IList<string> failedFiles = ValidateSymbols(ExtractSymbolsPackages(GetAllSymbolsPackages()), InitializeSourcelinkTool());
|
||||
|
||||
if (failedFiles.Count > 0)
|
||||
{
|
||||
OutputHelper.WriteLine($"Sourcelink verification failed for the following files:");
|
||||
foreach (string file in failedFiles)
|
||||
{
|
||||
OutputHelper.WriteLine(file);
|
||||
}
|
||||
}
|
||||
|
||||
Assert.True(failedFiles.Count == 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes sourcelink tool.
|
||||
/// Extracts the dotnet-sourcelink tool package from PSB arhive.
|
||||
/// </summary>
|
||||
/// <returns>Path to sourcelink tool binary.</returns>
|
||||
private string InitializeSourcelinkTool()
|
||||
{
|
||||
const string SourcelinkToolPackageNamePattern = "dotnet-sourcelink*nupkg";
|
||||
const string SourcelinkToolBinaryFilename = "dotnet-sourcelink.dll";
|
||||
|
||||
string toolPackageDir = Directory.CreateDirectory(Path.Combine(SourcelinkRoot, "sourcelink-tool")).FullName;
|
||||
Utilities.ExtractTarball(Config.SourceBuiltArtifactsPath, toolPackageDir, SourcelinkToolPackageNamePattern);
|
||||
|
||||
string extractedToolPath = Directory.CreateDirectory(Path.Combine(toolPackageDir, "extracted")).FullName;
|
||||
Utilities.ExtractNupkg(Utilities.GetFile(toolPackageDir, SourcelinkToolPackageNamePattern), extractedToolPath);
|
||||
|
||||
return Utilities.GetFile(extractedToolPath, SourcelinkToolBinaryFilename);
|
||||
}
|
||||
|
||||
private IEnumerable<string> GetAllSymbolsPackages()
|
||||
{
|
||||
/*
|
||||
At the moment we validate sourcelinks from runtime symbols package.
|
||||
The plan is to make symbols, from all repos, available in source-build artifacts.
|
||||
Once that's available, this code will be modified to validate all available symbols.
|
||||
Tracking issue: https://github.com/dotnet/source-build/issues/3612
|
||||
*/
|
||||
|
||||
// Runtime symbols package lives in the same directory as PSB artifacts.
|
||||
// i.e. <repo-root>/artifacts/x64/Release/runtime/dotnet-runtime-symbols-fedora.36-x64-8.0.0-preview.7.23355.7.tar.gz
|
||||
yield return Utilities.GetFile(Path.GetDirectoryName(Config.SourceBuiltArtifactsPath), "dotnet-runtime-symbols-*.tar.gz");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts symbols packages to subdirectories of the common symbols root directory.
|
||||
/// </summary>
|
||||
/// <returns>Path to common symbols root directory.</returns>
|
||||
private string ExtractSymbolsPackages(IEnumerable<string> packages)
|
||||
{
|
||||
string symbolsRoot = Directory.CreateDirectory(Path.Combine(SourcelinkRoot, "symbols")).FullName;
|
||||
|
||||
foreach (string package in packages)
|
||||
{
|
||||
Assert.True(package.EndsWith(".tar.gz"), $"Package extension is not supported: {package}");
|
||||
DirectoryInfo targetDirInfo = Directory.CreateDirectory(Path.Combine(symbolsRoot, Path.GetFileNameWithoutExtension(package)));
|
||||
Utilities.ExtractTarball(package, targetDirInfo.FullName, OutputHelper);
|
||||
}
|
||||
|
||||
return symbolsRoot;
|
||||
}
|
||||
|
||||
private IList<string> ValidateSymbols(string path, string sourcelinkToolPath)
|
||||
{
|
||||
Assert.True(Directory.Exists(path), $"Path, with symbol files to validate, does not exist: {path}");
|
||||
|
||||
var failedFiles = new ConcurrentBag<string>();
|
||||
|
||||
IEnumerable<string> allFiles = Directory.GetFiles(path, "*.pdb", SearchOption.AllDirectories);
|
||||
Parallel.ForEach(allFiles, file =>
|
||||
{
|
||||
(Process Process, string StdOut, string StdErr) executeResult = ExecuteHelper.ExecuteProcess(
|
||||
DotNetHelper.DotNetPath,
|
||||
$"{sourcelinkToolPath} test --offline {file}",
|
||||
OutputHelper,
|
||||
logOutput: false,
|
||||
excludeInfo: true, // Exclude info messages, as there can be 1,000+ processes
|
||||
millisecondTimeout: 5000,
|
||||
configureCallback: (process) => DotNetHelper.ConfigureProcess(process, null));
|
||||
|
||||
if (executeResult.Process.ExitCode != 0)
|
||||
{
|
||||
failedFiles.Add(file);
|
||||
}
|
||||
});
|
||||
|
||||
Assert.True(allFiles.Count() > 0, $"Did not find any symbols for sourcelink verification in {path}");
|
||||
|
||||
return failedFiles.ToList();
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ using System.IO;
|
|||
using System.IO.Compression;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.DotNet.SourceBuild.SmokeTests;
|
||||
|
@ -60,6 +61,19 @@ public static class Utilities
|
|||
}
|
||||
}
|
||||
|
||||
public static void ExtractNupkg(string package, string outputDir)
|
||||
{
|
||||
Directory.CreateDirectory(outputDir);
|
||||
|
||||
using ZipArchive zip = ZipFile.OpenRead(package);
|
||||
foreach (ZipArchiveEntry entry in zip.Entries)
|
||||
{
|
||||
string outputPath = Path.Combine(outputDir, entry.FullName);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
|
||||
entry.ExtractToFile(outputPath);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task RetryAsync(Func<Task> executor, ITestOutputHelper outputHelper)
|
||||
{
|
||||
await Utilities.RetryAsync(
|
||||
|
@ -104,4 +118,12 @@ public static class Utilities
|
|||
exception = await executor();
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetFile(string path, string pattern)
|
||||
{
|
||||
string[] files = Directory.GetFiles(path, pattern, SearchOption.AllDirectories);
|
||||
Assert.False(files.Length > 1, $"Found multiple files matching the pattern {pattern}: {Environment.NewLine}{string.Join(Environment.NewLine, files)}");
|
||||
Assert.False(files.Length == 0, $"Did not find any files matching the pattern {pattern}");
|
||||
return files[0];
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue