the browser-facing portion of osu!
at master 6.7 kB view raw
1<?php 2 3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0. 4// See the LICENCE file in the repository root for full licence text. 5 6declare(strict_types=1); 7 8namespace Tests\Models\Multiplayer; 9 10use App\Exceptions\InvariantException; 11use App\Models\Beatmap; 12use App\Models\Multiplayer\PlaylistItem; 13use App\Models\Multiplayer\ScoreLink; 14use App\Models\ScoreToken; 15use Tests\TestCase; 16 17class ScoreLinkTest extends TestCase 18{ 19 private static array $commonScoreParams; 20 21 public static function setUpBeforeClass(): void 22 { 23 parent::setUpBeforeClass(); 24 static::$commonScoreParams = [ 25 'accuracy' => 0.5, 26 'ended_at' => new \DateTime(), 27 'max_combo' => 1, 28 'statistics' => [ 29 'great' => 1, 30 ], 31 'total_score' => 1, 32 ]; 33 } 34 35 public function testRequiredModsMissing() 36 { 37 $playlistItem = PlaylistItem::factory()->create([ 38 'required_mods' => [[ 39 'acronym' => 'HD', 40 ]], 41 ]); 42 $scoreToken = ScoreToken::factory()->create([ 43 'beatmap_id' => $playlistItem->beatmap_id, 44 'playlist_item_id' => $playlistItem, 45 ]); 46 47 $this->expectException(InvariantException::class); 48 $this->expectExceptionMessage('This play does not include the mods required.'); 49 ScoreLink::complete($scoreToken, [ 50 ...static::$commonScoreParams, 51 'beatmap_id' => $playlistItem->beatmap_id, 52 'ruleset_id' => $playlistItem->ruleset_id, 53 'user_id' => $scoreToken->user_id, 54 ]); 55 } 56 57 public function testRequiredModsPresent() 58 { 59 $playlistItem = PlaylistItem::factory()->create([ 60 'required_mods' => [[ 61 'acronym' => 'HD', 62 ]], 63 ]); 64 $scoreToken = ScoreToken::factory()->create([ 65 'beatmap_id' => $playlistItem->beatmap_id, 66 'playlist_item_id' => $playlistItem, 67 ]); 68 69 $this->expectNotToPerformAssertions(); 70 ScoreLink::complete($scoreToken, [ 71 ...static::$commonScoreParams, 72 'beatmap_id' => $playlistItem->beatmap_id, 73 'mods' => [['acronym' => 'HD']], 74 'ruleset_id' => $playlistItem->ruleset_id, 75 'user_id' => $scoreToken->user_id, 76 ]); 77 } 78 79 public function testExpectedAllowedMod() 80 { 81 $playlistItem = PlaylistItem::factory()->create([ 82 'required_mods' => [[ 83 'acronym' => 'DT', 84 ]], 85 'allowed_mods' => [[ 86 'acronym' => 'HD', 87 ]], 88 ]); 89 $scoreToken = ScoreToken::factory()->create([ 90 'beatmap_id' => $playlistItem->beatmap_id, 91 'playlist_item_id' => $playlistItem, 92 ]); 93 94 $this->expectNotToPerformAssertions(); 95 ScoreLink::complete($scoreToken, [ 96 ...static::$commonScoreParams, 97 'beatmap_id' => $playlistItem->beatmap_id, 98 'mods' => [ 99 ['acronym' => 'DT'], 100 ['acronym' => 'HD'], 101 ], 102 'ruleset_id' => $playlistItem->ruleset_id, 103 'user_id' => $scoreToken->user_id, 104 ]); 105 } 106 107 public function testUnexpectedAllowedMod() 108 { 109 $playlistItem = PlaylistItem::factory()->create([ 110 'required_mods' => [[ 111 'acronym' => 'DT', 112 ]], 113 'allowed_mods' => [[ 114 'acronym' => 'HR', 115 ]], 116 ]); 117 $scoreToken = ScoreToken::factory()->create([ 118 'beatmap_id' => $playlistItem->beatmap_id, 119 'playlist_item_id' => $playlistItem, 120 ]); 121 122 $this->expectException(InvariantException::class); 123 $this->expectExceptionMessage('This play includes mods that are not allowed.'); 124 ScoreLink::complete($scoreToken, [ 125 ...static::$commonScoreParams, 126 'beatmap_id' => $playlistItem->beatmap_id, 127 'mods' => [ 128 ['acronym' => 'DT'], 129 ['acronym' => 'HD'], 130 ], 131 'ruleset_id' => $playlistItem->ruleset_id, 132 'user_id' => $scoreToken->user_id, 133 ]); 134 } 135 136 public function testUnexpectedModWhenNoModsAreAllowed() 137 { 138 $playlistItem = PlaylistItem::factory()->create(); // no required or allowed mods. 139 $scoreToken = ScoreToken::factory()->create([ 140 'beatmap_id' => $playlistItem->beatmap_id, 141 'playlist_item_id' => $playlistItem, 142 ]); 143 144 $this->expectException(InvariantException::class); 145 $this->expectExceptionMessage('This play includes mods that are not allowed.'); 146 ScoreLink::complete($scoreToken, [ 147 ...static::$commonScoreParams, 148 'beatmap_id' => $playlistItem->beatmap_id, 149 'mods' => [['acronym' => 'HD']], 150 'ruleset_id' => $playlistItem->ruleset_id, 151 'user_id' => $scoreToken->user_id, 152 ]); 153 } 154 155 public function testUnexpectedModAcceptedIfAlwaysValidForSubmission() 156 { 157 $beatmap = Beatmap::factory()->create([ 158 'playmode' => 0, // must be osu! specifically. no other ruleset currently has an appropriate mod. 159 ]); 160 $playlistItem = PlaylistItem::factory()->create([ 161 'ruleset_id' => 0, 162 'beatmap_id' => $beatmap, 163 // no required or allowed mods. 164 ]); 165 $scoreToken = ScoreToken::factory()->create([ 166 'beatmap_id' => $playlistItem->beatmap_id, 167 'playlist_item_id' => $playlistItem, 168 ]); 169 170 $this->expectNotToPerformAssertions(); 171 ScoreLink::complete($scoreToken, [ 172 ...static::$commonScoreParams, 173 'beatmap_id' => $playlistItem->beatmap_id, 174 'mods' => [['acronym' => 'TD']], 175 'ruleset_id' => $playlistItem->ruleset_id, 176 'user_id' => $scoreToken->user_id, 177 ]); 178 } 179 180 public function testFailedMultiplayerScoresArePreserved() 181 { 182 $playlistItem = PlaylistItem::factory()->create(); 183 $scoreToken = ScoreToken::factory()->create([ 184 'beatmap_id' => $playlistItem->beatmap_id, 185 'playlist_item_id' => $playlistItem, 186 ]); 187 188 $scoreLink = ScoreLink::complete($scoreToken, [ 189 ...static::$commonScoreParams, 190 'beatmap_id' => $playlistItem->beatmap_id, 191 'ruleset_id' => $playlistItem->ruleset_id, 192 'user_id' => $scoreToken->user_id, 193 'passed' => false, 194 ]); 195 $this->assertTrue($scoreLink->score->preserve); 196 } 197}