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
6namespace Tests\Commands;
7
8use App\Exceptions\InvariantException;
9use App\Models\Solo\Score;
10use Artisan;
11use LaravelRedis;
12use Tests\TestCase;
13
14class EsIndexScoresQueueTest extends TestCase
15{
16 const SCHEMA = 'test_queue_command';
17
18 private static function clearQueue(): void
19 {
20 LaravelRedis::del(static::queueKey());
21 }
22
23 private static function queueKey(): string
24 {
25 return 'osu-queue:'.static::SCHEMA;
26 }
27
28 private static function queueSize(): int
29 {
30 return LaravelRedis::llen(static::queueKey());
31 }
32
33 /**
34 * @dataProvider dataProviderForTestParameterValidity
35 */
36 public function testParameterValidity(array $params, bool $isValid)
37 {
38 if (!$isValid) {
39 $this->expectException(InvariantException::class);
40 }
41
42 $command = $this->artisan('es:index-scores:queue', array_merge($params, ['--schema' => static::SCHEMA]));
43
44 if ($isValid) {
45 $command->expectsQuestion('This will queue scores for indexing to schema '.static::SCHEMA.', continue?', 'yes');
46 }
47 }
48
49 /**
50 * @dataProvider dataProviderForTestQueueScores
51 */
52 public function testQueueScores(callable $setUp, array|callable $params, int $change): void
53 {
54 $setUp();
55
56 $this->expectCountChange(fn () => static::queueSize(), $change);
57 Artisan::call(
58 'es:index-scores:queue',
59 array_merge(is_callable($params) ? $params() : $params, [
60 '--no-interaction' => true,
61 '--schema' => static::SCHEMA,
62 ]),
63 );
64 }
65
66 public static function dataProviderForTestParameterValidity(): array
67 {
68 return [
69 [[], false],
70 [['--all' => true], true],
71 [['--from' => 0], true],
72 [['--ids' => 0], true],
73 [['--ids' => ''], false],
74 [['--ids' => ','], false],
75 [['--ids' => '1,2'], true],
76 [['--ids' => [1,2]], true],
77 [['--all' => true, '--from' => 0], false],
78 [['--all' => true, '--ids' => 0], false],
79 [['--from' => 0, '--ids' => 0], false],
80 [['--user' => 0], false],
81 [['--user' => 0, '--all' => true], true],
82 [['--user' => 0, '--all' => true, '--from' => 0], false],
83 ];
84 }
85
86 public static function dataProviderForTestQueueScores(): array
87 {
88 $userId = 0;
89 $setUp = function () use ($userId) {
90 static::clearQueue();
91 Score::factory()->count(10)->create();
92 $scores = Score::orderBy('id')->get()->all();
93 foreach ([$scores[0], $scores[1], $scores[2], $scores[9]] as $score) {
94 $score->update(['user_id' => $userId]);
95 }
96 };
97
98 return [
99 [$setUp, ['--all' => true], 10],
100 [$setUp, fn (): array => [
101 '--ids' => Score::inRandomOrder()->limit(3)->pluck('id')->join(','),
102 ], 3],
103 [$setUp, fn (): array => ['--from' => Score::max('id') - 1], 1],
104 [$setUp, ['--all' => true, '--user' => $userId], 4],
105 [$setUp, fn (): array => [
106 '--user' => $userId,
107 // get id of second last score to cover last two scores
108 // but only one is expected to be queued due to user filter
109 '--from' => Score::orderBy('id', 'DESC')->limit(2)->get()->all()[1]->getKey() - 1,
110 ], 1],
111 ];
112 }
113}