Skip to content

Commit 59a03d8

Browse files
Fix TestMissingScores NullReferenceException and parallelize CI test matrix
ResultsScreen.cs: GetBeatmapAsync can return null when the online ID is unknown (e.g. in the TestMissingScores test which returns empty scores). Replace the null-forgiving ! with a proper ??= placeholder matching the SubScreenBeatmapSelect pattern. Fixes the Linux test-results reporter failure. ci.yml: Split the test matrix into two parallel groups per OS (game: osu.Game.Tests + Tournament + Templates; rulesets: 4 ruleset DLLs). Each group runs in ~half the total time, so Windows runners (~2-3× slower than Linux) complete each group in ~60 min instead of exceeding the 120 min wall-clock budget for the full suite. Per-job timeout reduced from 120 → 90 min (right-sized for a single group). Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/4f0e240e-6ec5-4f03-abaf-c0a6e6e7a448 Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
1 parent c949d87 commit 59a03d8

2 files changed

Lines changed: 32 additions & 12 deletions

File tree

.github/workflows/ci.yml

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,21 @@ jobs:
8787
# - { prettyname: macOS, fullname: macos-latest }
8888
- { prettyname: Linux, fullname: ubuntu-latest }
8989
threadingMode: ['MultiThreaded']
90-
timeout-minutes: 120
90+
# Split tests into two parallel groups so Windows runners (which are ~2-3× slower than
91+
# Linux) finish each group in ~60 min rather than timing out on the full suite at 120 min.
92+
testSuite:
93+
- name: game
94+
dlls: >-
95+
osu.Game.Tests/bin/Debug/**/osu.Game.Tests.dll
96+
osu.Game.Tournament.Tests/bin/Debug/**/osu.Game.Tournament.Tests.dll
97+
Templates/**/*.Tests/bin/Debug/**/*.Tests.dll
98+
- name: rulesets
99+
dlls: >-
100+
osu.Game.Rulesets.Osu.Tests/bin/Debug/**/osu.Game.Rulesets.Osu.Tests.dll
101+
osu.Game.Rulesets.Taiko.Tests/bin/Debug/**/osu.Game.Rulesets.Taiko.Tests.dll
102+
osu.Game.Rulesets.Catch.Tests/bin/Debug/**/osu.Game.Rulesets.Catch.Tests.dll
103+
osu.Game.Rulesets.Mania.Tests/bin/Debug/**/osu.Game.Rulesets.Mania.Tests.dll
104+
timeout-minutes: 90
91105
steps:
92106
- name: Checkout
93107
uses: actions/checkout@v6
@@ -116,14 +130,8 @@ jobs:
116130
continue-on-error: true
117131
run: >
118132
dotnet test
119-
osu.Game.Tests/bin/Debug/**/osu.Game.Tests.dll
120-
osu.Game.Rulesets.Osu.Tests/bin/Debug/**/osu.Game.Rulesets.Osu.Tests.dll
121-
osu.Game.Rulesets.Taiko.Tests/bin/Debug/**/osu.Game.Rulesets.Taiko.Tests.dll
122-
osu.Game.Rulesets.Catch.Tests/bin/Debug/**/osu.Game.Rulesets.Catch.Tests.dll
123-
osu.Game.Rulesets.Mania.Tests/bin/Debug/**/osu.Game.Rulesets.Mania.Tests.dll
124-
osu.Game.Tournament.Tests/bin/Debug/**/osu.Game.Tournament.Tests.dll
125-
Templates/**/*.Tests/bin/Debug/**/*.Tests.dll
126-
--logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx"
133+
${{matrix.testSuite.dlls}}
134+
--logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}-${{matrix.testSuite.name}}.trx"
127135
--
128136
NUnit.ConsoleOut=0
129137
@@ -133,8 +141,8 @@ jobs:
133141
uses: actions/upload-artifact@v7
134142
if: ${{ !cancelled() }}
135143
with:
136-
name: osu-test-results-${{matrix.os.prettyname}}-${{matrix.threadingMode}}
137-
path: ${{github.workspace}}/TestResults/TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx
144+
name: osu-test-results-${{matrix.os.prettyname}}-${{matrix.threadingMode}}-${{matrix.testSuite.name}}
145+
path: ${{github.workspace}}/TestResults/TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}-${{matrix.testSuite.name}}.trx
138146

139147
test-results:
140148
name: Test results

osu.Game/Screens/OnlinePlay/Matchmaking/RankedPlay/ResultsScreen.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,19 @@ private async Task fetchFinalScores()
125125
};
126126

127127
// Should complete instantaneously due to prior lookups.
128-
APIBeatmap beatmap = (await beatmapLookupCache.GetBeatmapAsync(globalBeatmap.Value.BeatmapInfo.OnlineID).ConfigureAwait(false))!;
128+
// GetBeatmapAsync can return null if the online ID is unknown (e.g. in tests or
129+
// when the API is unavailable); fall back to a placeholder rather than crashing.
130+
APIBeatmap? beatmap = await beatmapLookupCache.GetBeatmapAsync(globalBeatmap.Value.BeatmapInfo.OnlineID).ConfigureAwait(false);
131+
beatmap ??= new APIBeatmap
132+
{
133+
BeatmapSet = new APIBeatmapSet
134+
{
135+
Title = "unknown beatmap",
136+
TitleUnicode = "unknown beatmap",
137+
Artist = "unknown artist",
138+
ArtistUnicode = "unknown artist",
139+
}
140+
};
129141

130142
Schedule(() =>
131143
{

0 commit comments

Comments
 (0)