Skip to content

Commit

Permalink
Add GAP distro tests (#1067)
Browse files Browse the repository at this point in the history
  • Loading branch information
lgoettgens authored Jan 7, 2025
1 parent 99ddda8 commit cb8d2af
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 1 deletion.
105 changes: 105 additions & 0 deletions .github/workflows/CI-distro.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
name: Test GAP package distro

on:
push:
branches:
- 'master'
- 'release-*'
tags: '*'
pull_request:
schedule:
# Every Monday at 3:08 AM UTC
- cron: '8 3 * * 1'
workflow_dispatch:

concurrency:
# group by workflow and ref; the last slightly strange component ensures that for pull
# requests, we limit to 1 concurrent job, but for the default repository branch we don't
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref_name != github.event.repository.default_branch || github.run_number }}
# Cancel intermediate builds, but only if it is a pull request build.
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}

jobs:
generate-matrix:
runs-on: ubuntu-latest
outputs:
gap-packages: ${{ steps.set-matrix.outputs.gap-packages }}
steps:
- uses: actions/checkout@v4
- name: "Set up Julia"
uses: julia-actions/setup-julia@v2
with:
version: '1'
- name: "Cache artifacts"
uses: julia-actions/cache@v2
- name: "Build package"
uses: julia-actions/julia-buildpkg@v1
- name: Get list of GAP packages
id: set-matrix
run: julia --project=. -e '
using Artifacts, TOML;
output = sprint(print, "gap-packages=", map(name -> name[9:end], sort!(collect(filter(startswith("GAP_pkg_"), keys(TOML.parsefile(find_artifacts_toml(Base.active_project()))))))));
println(output);
open(ENV["GITHUB_OUTPUT"], "a") do io;
println(io, output);
end;'

test:
name: ${{ matrix.gap-package }}
needs: generate-matrix
runs-on: ${{ matrix.os }}
timeout-minutes: 20
continue-on-error: ${{ matrix.julia-version == 'nightly' }}
strategy:
fail-fast: false
matrix:
julia-version:
- '1'
julia-arch:
- x64
os:
- ubuntu-latest
gap-package: ${{fromJSON(needs.generate-matrix.outputs.gap-packages)}}
exclude:
- gap-package: 'alnuth' # `AL_EXECUTABLE, the executable for PARI/GP, has to be set`
- gap-package: 'atlasrep' # random segfaults during testing
- gap-package: 'autodoc' # tries and fails to build its own documentation, inside the (partially write protected) artifacts dir
- gap-package: 'example' # no jll
- gap-package: 'examplesforhomalg' # `Error, found no GAP executable in PATH`
- gap-package: 'guarana' # `AL_EXECUTABLE, the executable for PARI/GP, has to be set`
- gap-package: 'hap' # `polymake command not found. Please set POLYMAKE_COMMAND by hand`
- gap-package: 'hapcryst' # `polymake command not found. Please set POLYMAKE_COMMAND by hand`
- gap-package: 'help' # test failure in HeLP-4.0/tst/yes_4ti2.tst:39
- gap-package: 'io' # segfaults, most likely due to child process handling
- gap-package: 'itc' # dependency `xgap` has no jll
- gap-package: 'localizeringforhomalg' # `Error, found no GAP executable in PATH`
- gap-package: 'normalizinterface' # Tests fail: NormalizInterface currently bundles Normaliz 3.9.3 and its test suite is tuned to that, but our JLL builds it against normaliz_jll which has 3.10.2
- gap-package: 'packagemanager' # tests need curlInterface to passe, reactivate once we have a working JLL for that
- gap-package: 'polenta' # `AL_EXECUTABLE, the executable for PARI/GP, has to be set`
- gap-package: 'polycyclic' # test suite currently broken and also disabled by GAP package distribution
- gap-package: 'polymaking' # `polymake command not found. Please set POLYMAKE_COMMAND by hand`
- gap-package: 'profiling' # segfaults during testing
- gap-package: 'radiroot' # `AL_EXECUTABLE, the executable for PARI/GP, has to be set`
- gap-package: 'ringsforhomalg' # `Error, found no GAP executable in PATH`
- gap-package: 'semigroups' # no jll
- gap-package: 'xgap' # no jll

steps:
- uses: actions/checkout@v4
- name: "Install extra dependencies"
run: sudo apt-get install --no-install-recommends texlive-latex-base texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended dot2tex
- name: "Set up Julia"
uses: julia-actions/setup-julia@v2
with:
version: ${{ matrix.julia-version }}
arch: ${{ matrix.julia-arch }}
- name: "Cache artifacts"
uses: julia-actions/cache@v2
with:
include-matrix: false # don't create a cache per GAP package
cache-scratchspaces: false
- name: "Build package"
uses: julia-actions/julia-buildpkg@v1
- name: "Run GAP package tests"
run: |
julia --color=yes --project=. -e 'using GAP, Test; @test GAP.Packages.test("${{ matrix.gap-package }}")'
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- Update to GAP 4.14.0
- Add `GAP.Packages.build_recursive(name)`
- Add `GAP.Packages.test(name)`
- Change `GAP.Packages.build(name)` to no longer try to build the package if
it is already installed
- Instead of downloading a single huge "artifact" containing all deposited GAP
Expand Down
1 change: 1 addition & 0 deletions docs/src/packages.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ GAP.Packages.update
GAP.Packages.remove
GAP.Packages.build
GAP.Packages.build_recursive
GAP.Packages.test
GAP.Packages.locate_package
```

61 changes: 60 additions & 1 deletion src/packages.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module Packages

import Downloads
import Pidfile
import ...GAP: Globals, GapObj, replace_global!, RNamObj, sysinfo, Wrappers
import ...GAP: disable_error_handler, Globals, GapObj, replace_global!, RNamObj, sysinfo, Wrappers

const DEFAULT_PKGDIR = Ref{String}()
const DOWNLOAD_HELPER = Ref{Downloads.Downloader}()
Expand Down Expand Up @@ -453,6 +453,65 @@ function build_recursive(name::String; quiet::Bool = false,
return true
end

"""
test(name::String)
Run the tests of GAP package `name` and return a boolean indicating whether
they succeeded (`true`) or not.
It is intended to be used with the `@test` macro from the `Test` package.
The function uses [the GAP function `TestPackage`](GAP_ref(ref:TestPackage)).
"""
function test(name::String)
global disable_error_handler

function with_gap_var(f, name::Symbol, val)
gname = GapObj(name)
old_value = Globals.ValueGlobal(gname)
replace_global!(name, val)
try
f()
finally
replace_global!(name, old_value)
end
end

error_occurred = false
called_QuitGap = false
function fake_QuitGap(code)
called_QuitGap && return # only do something on the first call
called_QuitGap = true
if code != 0
error_occurred = true
end
return
end

disable_error_handler[] = true
result = false
try
with_gap_var(:ERROR_OUTPUT, Globals._JULIAINTERFACE_ORIGINAL_ERROR_OUTPUT) do
with_gap_var(:QuitGap, fake_QuitGap) do
with_gap_var(:QUIT_GAP, fake_QuitGap) do
with_gap_var(:ForceQuitGap, fake_QuitGap) do
with_gap_var(:FORCE_QUIT_GAP, fake_QuitGap) do
result = Globals.TestPackage(GapObj(name))
end
end
end
end
end
finally
disable_error_handler[] = false
end

# Due to the hack above, we run into an error in TestPackage that is usually unreachable.
# In the case of a `QuitGap` call, we thus don't check for `result == true`.
# Note: `result` may be `fail`, so it is not always booleany.
return !error_occurred && (called_QuitGap || result == true)
end

"""
locate_package(name::String)
Expand Down

0 comments on commit cb8d2af

Please sign in to comment.