From 1872fe6219b136128dcf45e3ea36df41931b5db2 Mon Sep 17 00:00:00 2001 From: Omair Majid Date: Thu, 14 Apr 2022 13:41:09 -0400 Subject: [PATCH] Add support for filtering on musl libc Parse `ldd --version` output and use that to detect musl-based platforms. Add the additional RIDs `linux-musl` and `linux-musl-$ARCH` for them, so those strings can be used to filter tests on those platforms. Also remove the last version number string from Alpine, Rocky, Alma and Oracle Linux. Add alpine to CI matrix, and enable unit tests for it. I am not enabling reproducers on it right now, because that needs fixes from https://github.com/redhat-developer/dotnet-regular-tests/pull/192 to be merged first. --- .github/workflows/ci.yml | 30 +++++++++++++++- Makefile | 2 +- README.md | 10 ++++-- Samples/NonAlpineBashTest/test.json | 13 +++++++ Samples/NonAlpineBashTest/test.sh | 5 +++ Turkey.Tests/PlatformIdTest.cs | 36 +++++++++++++------- Turkey/AssemblyInfo.cs | 3 ++ Turkey/PlatformId.cs | 53 +++++++++++++++++++++++------ 8 files changed, 125 insertions(+), 27 deletions(-) create mode 100644 Samples/NonAlpineBashTest/test.json create mode 100755 Samples/NonAlpineBashTest/test.sh create mode 100644 Turkey/AssemblyInfo.cs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 10e4595..9195043 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,8 +14,11 @@ jobs: fail-fast: false matrix: container_image: + - docker.io/library/alpine:edge + - docker.io/library/alpine:latest - registry.fedoraproject.org/fedora:34 - registry.fedoraproject.org/fedora:35 + - registry.fedoraproject.org/fedora:36 - registry.fedoraproject.org/fedora:rawhide - registry.access.redhat.com/ubi8 dotnet_version: @@ -25,6 +28,8 @@ jobs: exclude: - container_image: registry.fedoraproject.org/fedora:rawhide dotnet_version: "5.0" + - container_image: registry.fedoraproject.org/fedora:36 + dotnet_version: "5.0" container: image: ${{ matrix.container_image }} @@ -34,13 +39,36 @@ jobs: - name: Install build dependencies timeout-minutes: 5 run: | - dnf install -y dotnet-sdk-${{ matrix.dotnet_version }} make + set -euo pipefail + if command -v dnf; then + dnf install -y dotnet-sdk-${{ matrix.dotnet_version }} git make + elif command -v apk; then + apk add bash curl git icu-libs krb5-libs libgcc libintl libssl1.1 libstdc++ make zlib + curl -sSLO https://dot.net/v1/dotnet-install.sh + chmod +x ./dotnet-install.sh + ./dotnet-install.sh --channel ${{ matrix.dotnet_version }} + fi - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Sanity check + run: | + set -euo pipefail + PATH=$PATH:$HOME/.dotnet/ + + git config --global safe.directory "$GITHUB_WORKSPACE" + + make + mkdir -p no-reproducers + dotnet turkey/Turkey.dll no-reproducers - name: Run tests run: | set -euo pipefail + PATH=$PATH:$HOME/.dotnet/ + make check reproducers: diff --git a/Makefile b/Makefile index 9ef8fa4..4024722 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ check: run-samples: rm -rf ~/.nuget.orig && mv ~/.nuget ~/.nuget.orig && mkdir -p ~/.nuget - cd Samples && test -f ../bin/turkey && (../bin/turkey || true) + cd Samples && test -f ../turkey/Turkey.dll && (dotnet ../turkey/Turkey.dll || true) rm -rf ~/.nuget && mv ~/.nuget.orig ~/.nuget publish: diff --git a/README.md b/README.md index 8c0b2e6..849ec92 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,13 @@ It produces results in various forms, including a junit-compatible xml file. # Supported Platforms and Architectures -This is fully usable on GNU libc-based Linux distributions. This is -used by Red Hat to run .NET tests on Fedora and RHEL on multiple -architectures including 64-bit ARM, Intel x86_64 and IBM Z. +This is fully usable on GNU libc-based and musl libc-based Linux distributions. + +This is used by Red Hat to run .NET tests on Fedora and RHEL on multiple +architectures including 64-bit ARM (`aarch64`), Intel x86_64 (`x86_64`) and IBM +Z (`s390x`). + +It's also being used by other distributions, such as Alpine. # Building diff --git a/Samples/NonAlpineBashTest/test.json b/Samples/NonAlpineBashTest/test.json new file mode 100644 index 0000000..3bd0732 --- /dev/null +++ b/Samples/NonAlpineBashTest/test.json @@ -0,0 +1,13 @@ +{ + "name": "NonAlpineBashTest", + "enabled": true, + "requiresSdk": true, + "version": "1.0", + "versionSpecific": false, + "type": "bash", + "cleanup": true, + "ignoredRIDs":[ + "alpine" + ] +} + diff --git a/Samples/NonAlpineBashTest/test.sh b/Samples/NonAlpineBashTest/test.sh new file mode 100755 index 0000000..20566a4 --- /dev/null +++ b/Samples/NonAlpineBashTest/test.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +echo "${@}" + +true diff --git a/Turkey.Tests/PlatformIdTest.cs b/Turkey.Tests/PlatformIdTest.cs index f6982b7..c5da86e 100644 --- a/Turkey.Tests/PlatformIdTest.cs +++ b/Turkey.Tests/PlatformIdTest.cs @@ -8,20 +8,32 @@ namespace Turkey.Tests public class PlatformIdTest { [Theory] - [InlineData(new string[] { "ID=fedora", "VERSION_ID=9" }, "x64", new string[] { "linux", "linux-x64", "fedora", "fedora-x64", "fedora9", "fedora.9", "fedora.9-x64" })] - [InlineData(new string[] { "ID=fedora", "VERSION_ID=30" }, "x64", new string[] { "linux", "linux-x64", "fedora", "fedora-x64", "fedora30", "fedora.30", "fedora.30-x64" })] - [InlineData(new string[] { "ID=fedora", "VERSION_ID=30" }, "arm64", new string[] { "linux", "linux-arm64", "fedora", "fedora-arm64", "fedora30", "fedora.30", "fedora.30-arm64" })] - [InlineData(new string[] { "ID=rhel", "VERSION_ID=7" }, "x64", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel7", "rhel.7", "rhel.7-x64" })] - [InlineData(new string[] { "ID=rhel", "VERSION_ID=7.3" }, "x64", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel7", "rhel.7", "rhel.7-x64" })] - [InlineData(new string[] { "ID=rhel", "VERSION_ID=8" }, "x64", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel8", "rhel.8", "rhel.8-x64" })] - [InlineData(new string[] { "ID=rhel", "VERSION_ID=8.0" }, "x64", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel8", "rhel.8", "rhel.8-x64" })] - [InlineData(new string[] { "ID=rhel", "VERSION_ID=8.1" }, "x64", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel8", "rhel.8", "rhel.8-x64" })] - [InlineData(new string[] { "ID=\"rhel\"", "VERSION_ID=\"8.1\"" }, "x64", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel8", "rhel.8", "rhel.8-x64" })] - [InlineData(new string[] { "ID=centos", "VERSION_ID=8" }, "x64", new string[] { "linux", "linux-x64", "centos", "centos-x64", "centos8", "centos.8", "centos.8-x64" })] - public void BasicPlatformIds(string[] lines, string architecture, string[] expectedIds) + [InlineData(new string[] { "ID=fedora", "VERSION_ID=9" }, "x64", "", new string[] { "linux", "linux-x64", "fedora", "fedora-x64", "fedora9", "fedora.9", "fedora.9-x64" })] + [InlineData(new string[] { "ID=fedora", "VERSION_ID=30" }, "x64", "", new string[] { "linux", "linux-x64", "fedora", "fedora-x64", "fedora30", "fedora.30", "fedora.30-x64" })] + [InlineData(new string[] { "ID=fedora", "VERSION_ID=30" }, "arm64", "", new string[] { "linux", "linux-arm64", "fedora", "fedora-arm64", "fedora30", "fedora.30", "fedora.30-arm64" })] + [InlineData(new string[] { "ID=rocky", "VERSION_ID=8.5" }, "x64", "", new string[] { "linux", "linux-x64", "rocky", "rocky-x64", "rocky8", "rocky.8", "rocky.8-x64" })] + [InlineData(new string[] { "ID=rhel", "VERSION_ID=7" }, "x64", "", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel7", "rhel.7", "rhel.7-x64" })] + [InlineData(new string[] { "ID=rhel", "VERSION_ID=7.3" }, "x64", "", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel7", "rhel.7", "rhel.7-x64" })] + [InlineData(new string[] { "ID=rhel", "VERSION_ID=8" }, "x64", "", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel8", "rhel.8", "rhel.8-x64" })] + [InlineData(new string[] { "ID=rhel", "VERSION_ID=8.0" }, "x64", "", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel8", "rhel.8", "rhel.8-x64" })] + [InlineData(new string[] { "ID=rhel", "VERSION_ID=8.1" }, "x64", "", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel8", "rhel.8", "rhel.8-x64" })] + [InlineData(new string[] { "ID=\"rhel\"", "VERSION_ID=\"8.1\"" }, "x64", "", new string[] { "linux", "linux-x64", "rhel", "rhel-x64", "rhel8", "rhel.8", "rhel.8-x64" })] + [InlineData(new string[] { "ID=centos", "VERSION_ID=8" }, "x64", "", new string[] { "linux", "linux-x64", "centos", "centos-x64", "centos8", "centos.8", "centos.8-x64" })] + [InlineData(new string[] { "ID=alpine", "VERSION_ID=3.15.2" }, "x64", "", new string[] { "linux", "linux-x64", "alpine", "alpine-x64", "alpine3.15", "alpine.3.15", "alpine.3.15-x64" })] + [InlineData(new string[] { "ID=alpine", "VERSION_ID=3.15.2" }, "x64", "musl libc", new string[] { "linux", "linux-x64", "alpine", "alpine-x64", "alpine3.15", "alpine.3.15", "alpine.3.15-x64", "linux-musl", "linux-musl-x64" })] + [InlineData(new string[] { "ID=fedora", "VERSION_ID=39" }, "x64", "GNU libc", new string[] { "linux", "linux-x64", "fedora", "fedora-x64", "fedora39", "fedora.39", "fedora.39-x64" })] + public void BasicPlatformIds(string[] osReleaseLines, string architecture, string lddOutput, string[] expectedIds) { - var result = new PlatformId().GetPlatformIdsFromOsRelease(lines, architecture); + var result = new PlatformId().ComputePlatformIds(osReleaseLines, architecture, lddOutput); Assert.Equal(expectedIds.ToList(), result); } + + [Fact] + public void LddWorks() + { + string version = new PlatformId().GetLddVersion(); + Assert.NotNull(version); + Assert.NotEmpty(version); + } } } diff --git a/Turkey/AssemblyInfo.cs b/Turkey/AssemblyInfo.cs new file mode 100644 index 0000000..2dde274 --- /dev/null +++ b/Turkey/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly:InternalsVisibleTo("Turkey.Tests")] diff --git a/Turkey/PlatformId.cs b/Turkey/PlatformId.cs index 6d343dc..cae1728 100644 --- a/Turkey/PlatformId.cs +++ b/Turkey/PlatformId.cs @@ -2,7 +2,9 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Diagnostics; namespace Turkey { @@ -11,37 +13,53 @@ public class PlatformId public List CurrentIds { // TODO make this async? - get => GetPlatformIdsFromOsRelease(File.ReadAllLines("/etc/os-release")); + get => ComputePlatformIds(File.ReadAllLines("/etc/os-release"), GetLddVersion()); } - public List GetPlatformIdsFromOsRelease(string[] lines) + public List ComputePlatformIds(string[] osReleaseLines, string lddVersionOutput) { string arch = Enum.GetName(typeof(Architecture), RuntimeInformation.OSArchitecture).ToLowerInvariant(); - return GetPlatformIdsFromOsRelease(lines, arch); + return ComputePlatformIds(osReleaseLines, arch, lddVersionOutput); } - public List GetPlatformIdsFromOsRelease(string[] lines, string architecture) + public List ComputePlatformIds(string[] osReleaseLines, string architecture, string lddVersionOutput) { - var id = GetValue("ID", lines); + var id = GetValue("ID", osReleaseLines); id = Unquote(id); - var versionId = GetValue("VERSION_ID", lines); + var versionId = GetValue("VERSION_ID", osReleaseLines); versionId = Unquote(versionId); - if (id.Equals("rhel", StringComparison.Ordinal)) + var needsLastVersionRemoved = new string[] { "almalinux", "alpine", "ol", "rhel", "rocky" } + .Any(os => id.Equals(os, StringComparison.Ordinal)); + if (needsLastVersionRemoved) { - int indexOfDot = versionId.IndexOf(".", StringComparison.Ordinal); + int indexOfDot = versionId.LastIndexOf(".", StringComparison.Ordinal); if (indexOfDot > 0) { versionId = versionId.Substring(0, indexOfDot); } } - var platforms = new string[] { + var platforms = new List() + { "linux", "linux" + "-" + architecture, id, id + "-" + architecture, id + versionId, id + "." + versionId, - id + "." + versionId + "-" + architecture }; + id + "." + versionId + "-" + architecture + }; + + bool isMusl = lddVersionOutput.Contains("musl", StringComparison.Ordinal); + + if (isMusl) + { + platforms.AddRange(new [] + { + "linux-musl", + "linux-musl" + "-" + architecture, + }); + + } return platforms.ToList(); } @@ -62,5 +80,20 @@ private string Unquote(string text) return text; } + + internal string GetLddVersion() + { + using (Process p = new Process()) + { + p.StartInfo.FileName = "ldd"; + p.StartInfo.Arguments = "--version"; + p.StartInfo.RedirectStandardError = true; + p.StartInfo.RedirectStandardOutput = true; + p.Start(); + p.WaitForExit(); + + return string.Concat(p.StandardOutput.ReadToEnd(), p.StandardError.ReadToEnd()); + } + } } }