Completed
Push — master ( 5d14f8...2337bd )
by Robin
27:19 queued 16s
created
apps/encryption/tests/Crypto/CryptTest.php 1 patch
Indentation   +407 added lines, -407 removed lines patch added patch discarded remove patch
@@ -19,411 +19,411 @@
 block discarded – undo
19 19
 use Test\TestCase;
20 20
 
21 21
 class CryptTest extends TestCase {
22
-	protected LoggerInterface&MockObject $logger;
23
-	protected IUserSession&MockObject $userSession;
24
-	protected IConfig&MockObject $config;
25
-	protected IL10N&MockObject $l;
26
-
27
-	protected Crypt $crypt;
28
-
29
-	protected function setUp(): void {
30
-		parent::setUp();
31
-
32
-		$this->logger = $this->getMockBuilder(LoggerInterface::class)
33
-			->disableOriginalConstructor()
34
-			->getMock();
35
-		$this->logger->expects($this->any())
36
-			->method('warning');
37
-		$this->userSession = $this->getMockBuilder(IUserSession::class)
38
-			->disableOriginalConstructor()
39
-			->getMock();
40
-		$this->config = $this->getMockBuilder(IConfig::class)
41
-			->disableOriginalConstructor()
42
-			->getMock();
43
-		$this->l = $this->createMock(IL10N::class);
44
-
45
-		$this->crypt = new Crypt($this->logger, $this->userSession, $this->config, $this->l);
46
-	}
47
-
48
-	/**
49
-	 * test getOpenSSLConfig without any additional parameters
50
-	 */
51
-	public function testGetOpenSSLConfigBasic(): void {
52
-		$this->config->expects($this->once())
53
-			->method('getSystemValue')
54
-			->with($this->equalTo('openssl'), $this->equalTo([]))
55
-			->willReturn([]);
56
-
57
-		$result = self::invokePrivate($this->crypt, 'getOpenSSLConfig');
58
-		$this->assertSame(1, count($result));
59
-		$this->assertArrayHasKey('private_key_bits', $result);
60
-		$this->assertSame(4096, $result['private_key_bits']);
61
-	}
62
-
63
-	/**
64
-	 * test getOpenSSLConfig with additional parameters defined in config.php
65
-	 */
66
-	public function testGetOpenSSLConfig(): void {
67
-		$this->config->expects($this->once())
68
-			->method('getSystemValue')
69
-			->with($this->equalTo('openssl'), $this->equalTo([]))
70
-			->willReturn(['foo' => 'bar', 'private_key_bits' => 1028]);
71
-
72
-		$result = self::invokePrivate($this->crypt, 'getOpenSSLConfig');
73
-		$this->assertSame(2, count($result));
74
-		$this->assertArrayHasKey('private_key_bits', $result);
75
-		$this->assertArrayHasKey('foo', $result);
76
-		$this->assertSame(1028, $result['private_key_bits']);
77
-		$this->assertSame('bar', $result['foo']);
78
-	}
79
-
80
-
81
-	/**
82
-	 * test generateHeader with valid key formats
83
-	 */
84
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataTestGenerateHeader')]
85
-	public function testGenerateHeader($keyFormat, $expected): void {
86
-		$this->config->expects($this->once())
87
-			->method('getSystemValueString')
88
-			->with($this->equalTo('cipher'), $this->equalTo('AES-256-CTR'))
89
-			->willReturn('AES-128-CFB');
90
-
91
-		if ($keyFormat) {
92
-			$result = $this->crypt->generateHeader($keyFormat);
93
-		} else {
94
-			$result = $this->crypt->generateHeader();
95
-		}
96
-
97
-		$this->assertSame($expected, $result);
98
-	}
99
-
100
-	/**
101
-	 * test generateHeader with invalid key format
102
-	 *
103
-	 */
104
-	public function testGenerateHeaderInvalid(): void {
105
-		$this->expectException(\InvalidArgumentException::class);
106
-
107
-		$this->crypt->generateHeader('unknown');
108
-	}
109
-
110
-	public static function dataTestGenerateHeader(): array {
111
-		return [
112
-			[null, 'HBEGIN:cipher:AES-128-CFB:keyFormat:hash2:encoding:binary:HEND'],
113
-			['password', 'HBEGIN:cipher:AES-128-CFB:keyFormat:password:encoding:binary:HEND'],
114
-			['hash', 'HBEGIN:cipher:AES-128-CFB:keyFormat:hash:encoding:binary:HEND']
115
-		];
116
-	}
117
-
118
-	public function testGetCipherWithInvalidCipher(): void {
119
-		$this->config->expects($this->once())
120
-			->method('getSystemValueString')
121
-			->with($this->equalTo('cipher'), $this->equalTo('AES-256-CTR'))
122
-			->willReturn('Not-Existing-Cipher');
123
-		$this->logger
124
-			->expects($this->once())
125
-			->method('warning')
126
-			->with('Unsupported cipher (Not-Existing-Cipher) defined in config.php supported. Falling back to AES-256-CTR');
127
-
128
-		$this->assertSame('AES-256-CTR', $this->crypt->getCipher());
129
-	}
130
-
131
-	/**
132
-	 * @param string $configValue
133
-	 * @param string $expected
134
-	 */
135
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataProviderGetCipher')]
136
-	public function testGetCipher($configValue, $expected): void {
137
-		$this->config->expects($this->once())
138
-			->method('getSystemValueString')
139
-			->with($this->equalTo('cipher'), $this->equalTo('AES-256-CTR'))
140
-			->willReturn($configValue);
141
-
142
-		$this->assertSame($expected,
143
-			$this->crypt->getCipher()
144
-		);
145
-	}
146
-
147
-	/**
148
-	 * data provider for testGetCipher
149
-	 */
150
-	public static function dataProviderGetCipher(): array {
151
-		return [
152
-			['AES-128-CFB', 'AES-128-CFB'],
153
-			['AES-256-CFB', 'AES-256-CFB'],
154
-			['AES-128-CTR', 'AES-128-CTR'],
155
-			['AES-256-CTR', 'AES-256-CTR'],
156
-
157
-			['unknown', 'AES-256-CTR']
158
-		];
159
-	}
160
-
161
-	/**
162
-	 * test concatIV()
163
-	 */
164
-	public function testConcatIV(): void {
165
-		$result = self::invokePrivate(
166
-			$this->crypt,
167
-			'concatIV',
168
-			['content', 'my_iv']);
169
-
170
-		$this->assertSame('content00iv00my_iv',
171
-			$result
172
-		);
173
-	}
174
-
175
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataTestSplitMetaData')]
176
-	public function testSplitMetaData($data, $expected): void {
177
-		$this->config->method('getSystemValueBool')
178
-			->with('encryption_skip_signature_check', false)
179
-			->willReturn(true);
180
-		$result = self::invokePrivate($this->crypt, 'splitMetaData', [$data, 'AES-256-CFB']);
181
-		$this->assertTrue(is_array($result));
182
-		$this->assertSame(3, count($result));
183
-		$this->assertArrayHasKey('encrypted', $result);
184
-		$this->assertArrayHasKey('iv', $result);
185
-		$this->assertArrayHasKey('signature', $result);
186
-		$this->assertSame($expected['encrypted'], $result['encrypted']);
187
-		$this->assertSame($expected['iv'], $result['iv']);
188
-		$this->assertSame($expected['signature'], $result['signature']);
189
-	}
190
-
191
-	public static function dataTestSplitMetaData(): array {
192
-		return [
193
-			['encryptedContent00iv001234567890123456xx',
194
-				['encrypted' => 'encryptedContent', 'iv' => '1234567890123456', 'signature' => false]],
195
-			['encryptedContent00iv00123456789012345600sig00e1992521e437f6915f9173b190a512cfc38a00ac24502db44e0ba10c2bb0cc86xxx',
196
-				['encrypted' => 'encryptedContent', 'iv' => '1234567890123456', 'signature' => 'e1992521e437f6915f9173b190a512cfc38a00ac24502db44e0ba10c2bb0cc86']],
197
-		];
198
-	}
199
-
200
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataTestHasSignature')]
201
-	public function testHasSignature($data, $expected): void {
202
-		$this->config->method('getSystemValueBool')
203
-			->with('encryption_skip_signature_check', false)
204
-			->willReturn(true);
205
-		$this->assertSame($expected,
206
-			$this->invokePrivate($this->crypt, 'hasSignature', [$data, 'AES-256-CFB'])
207
-		);
208
-	}
209
-
210
-	public static function dataTestHasSignature(): array {
211
-		return [
212
-			['encryptedContent00iv001234567890123456xx', false],
213
-			['encryptedContent00iv00123456789012345600sig00e1992521e437f6915f9173b190a512cfc38a00ac24502db44e0ba10c2bb0cc86xxx', true]
214
-		];
215
-	}
216
-
217
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataTestHasSignatureFail')]
218
-	public function testHasSignatureFail($cipher): void {
219
-		$this->expectException(GenericEncryptionException::class);
220
-
221
-		$data = 'encryptedContent00iv001234567890123456xx';
222
-		$this->invokePrivate($this->crypt, 'hasSignature', [$data, $cipher]);
223
-	}
224
-
225
-	public static function dataTestHasSignatureFail(): array {
226
-		return [
227
-			['AES-256-CTR'],
228
-			['aes-256-ctr'],
229
-			['AES-128-CTR'],
230
-			['ctr-256-ctr']
231
-		];
232
-	}
233
-
234
-	/**
235
-	 * test addPadding()
236
-	 */
237
-	public function testAddPadding(): void {
238
-		$result = self::invokePrivate($this->crypt, 'addPadding', ['data']);
239
-		$this->assertSame('dataxxx', $result);
240
-	}
241
-
242
-	/**
243
-	 * test removePadding()
244
-	 *
245
-	 * @param $data
246
-	 * @param $expected
247
-	 */
248
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataProviderRemovePadding')]
249
-	public function testRemovePadding($data, $expected): void {
250
-		$result = self::invokePrivate($this->crypt, 'removePadding', [$data]);
251
-		$this->assertSame($expected, $result);
252
-	}
253
-
254
-	/**
255
-	 * data provider for testRemovePadding
256
-	 */
257
-	public static function dataProviderRemovePadding(): array {
258
-		return [
259
-			['dataxx', 'data'],
260
-			['data', false]
261
-		];
262
-	}
263
-
264
-	/**
265
-	 * test parseHeader()
266
-	 */
267
-	public function testParseHeader(): void {
268
-		$header = 'HBEGIN:foo:bar:cipher:AES-256-CFB:encoding:binary:HEND';
269
-		$result = self::invokePrivate($this->crypt, 'parseHeader', [$header]);
270
-
271
-		$this->assertTrue(is_array($result));
272
-		$this->assertSame(3, count($result));
273
-		$this->assertArrayHasKey('foo', $result);
274
-		$this->assertArrayHasKey('cipher', $result);
275
-		$this->assertArrayHasKey('encoding', $result);
276
-		$this->assertSame('bar', $result['foo']);
277
-		$this->assertSame('AES-256-CFB', $result['cipher']);
278
-		$this->assertSame('binary', $result['encoding']);
279
-	}
280
-
281
-	/**
282
-	 * test encrypt()
283
-	 *
284
-	 * @return string
285
-	 */
286
-	public function testEncrypt() {
287
-		$decrypted = 'content';
288
-		$password = 'password';
289
-		$cipher = 'AES-256-CTR';
290
-		$iv = self::invokePrivate($this->crypt, 'generateIv');
291
-
292
-		$this->assertTrue(is_string($iv));
293
-		$this->assertSame(16, strlen($iv));
294
-
295
-		$result = self::invokePrivate($this->crypt, 'encrypt', [$decrypted, $iv, $password, $cipher]);
296
-
297
-		$this->assertTrue(is_string($result));
298
-
299
-		return [
300
-			'password' => $password,
301
-			'iv' => $iv,
302
-			'cipher' => $cipher,
303
-			'encrypted' => $result,
304
-			'decrypted' => $decrypted];
305
-	}
306
-
307
-	/**
308
-	 * test decrypt()
309
-	 *
310
-	 * @depends testEncrypt
311
-	 */
312
-	public function testDecrypt($data): void {
313
-		$result = self::invokePrivate(
314
-			$this->crypt,
315
-			'decrypt',
316
-			[$data['encrypted'], $data['iv'], $data['password'], $data['cipher'], true]);
317
-
318
-		$this->assertSame($data['decrypted'], $result);
319
-	}
320
-
321
-	/**
322
-	 * test return values of valid ciphers
323
-	 */
324
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataTestGetKeySize')]
325
-	public function testGetKeySize($cipher, $expected): void {
326
-		$result = $this->invokePrivate($this->crypt, 'getKeySize', [$cipher]);
327
-		$this->assertSame($expected, $result);
328
-	}
329
-
330
-	/**
331
-	 * test exception if cipher is unknown
332
-	 *
333
-	 */
334
-	public function testGetKeySizeFailure(): void {
335
-		$this->expectException(\InvalidArgumentException::class);
336
-
337
-		$this->invokePrivate($this->crypt, 'getKeySize', ['foo']);
338
-	}
339
-
340
-	public static function dataTestGetKeySize(): array {
341
-		return [
342
-			['AES-256-CFB', 32],
343
-			['AES-128-CFB', 16],
344
-			['AES-256-CTR', 32],
345
-			['AES-128-CTR', 16],
346
-		];
347
-	}
348
-
349
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataTestDecryptPrivateKey')]
350
-	public function testDecryptPrivateKey($header, $privateKey, $expectedCipher, $isValidKey, $expected): void {
351
-		$this->config->method('getSystemValueBool')
352
-			->willReturnMap([
353
-				['encryption.legacy_format_support', false, true],
354
-				['encryption.use_legacy_base64_encoding', false, false],
355
-			]);
356
-
357
-		/** @var Crypt|\PHPUnit\Framework\MockObject\MockObject $crypt */
358
-		$crypt = $this->getMockBuilder(Crypt::class)
359
-			->setConstructorArgs([
360
-				$this->logger,
361
-				$this->userSession,
362
-				$this->config,
363
-				$this->l
364
-			])
365
-			->onlyMethods([
366
-				'parseHeader',
367
-				'generatePasswordHash',
368
-				'symmetricDecryptFileContent',
369
-				'isValidPrivateKey'
370
-			])
371
-			->getMock();
372
-
373
-		$crypt->expects($this->once())->method('parseHeader')->willReturn($header);
374
-		if (isset($header['keyFormat']) && $header['keyFormat'] === 'hash') {
375
-			$crypt->expects($this->once())->method('generatePasswordHash')->willReturn('hash');
376
-			$password = 'hash';
377
-		} else {
378
-			$crypt->expects($this->never())->method('generatePasswordHash');
379
-			$password = 'password';
380
-		}
381
-
382
-		$crypt->expects($this->once())->method('symmetricDecryptFileContent')
383
-			->with('privateKey', $password, $expectedCipher)->willReturn('key');
384
-		$crypt->expects($this->once())->method('isValidPrivateKey')->willReturn($isValidKey);
385
-
386
-		$result = $crypt->decryptPrivateKey($privateKey, 'password');
387
-
388
-		$this->assertSame($expected, $result);
389
-	}
390
-
391
-	public static function dataTestDecryptPrivateKey(): array {
392
-		return [
393
-			[['cipher' => 'AES-128-CFB', 'keyFormat' => 'password'], 'HBEGIN:HENDprivateKey', 'AES-128-CFB', true, 'key'],
394
-			[['cipher' => 'AES-256-CFB', 'keyFormat' => 'password'], 'HBEGIN:HENDprivateKey', 'AES-256-CFB', true, 'key'],
395
-			[['cipher' => 'AES-256-CFB', 'keyFormat' => 'password'], 'HBEGIN:HENDprivateKey', 'AES-256-CFB', false, false],
396
-			[['cipher' => 'AES-256-CFB', 'keyFormat' => 'hash'], 'HBEGIN:HENDprivateKey', 'AES-256-CFB', true, 'key'],
397
-			[['cipher' => 'AES-256-CFB'], 'HBEGIN:HENDprivateKey', 'AES-256-CFB', true, 'key'],
398
-			[[], 'privateKey', 'AES-128-CFB', true, 'key'],
399
-		];
400
-	}
401
-
402
-	public function testIsValidPrivateKey(): void {
403
-		$res = openssl_pkey_new();
404
-		openssl_pkey_export($res, $privateKey);
405
-
406
-		// valid private key
407
-		$this->assertTrue(
408
-			$this->invokePrivate($this->crypt, 'isValidPrivateKey', [$privateKey])
409
-		);
410
-
411
-		// invalid private key
412
-		$this->assertFalse(
413
-			$this->invokePrivate($this->crypt, 'isValidPrivateKey', ['foo'])
414
-		);
415
-	}
416
-
417
-	public function testMultiKeyEncrypt(): void {
418
-		$res = openssl_pkey_new();
419
-		openssl_pkey_export($res, $privateKey);
420
-		$publicKeyPem = openssl_pkey_get_details($res)['key'];
421
-		$publicKey = openssl_pkey_get_public($publicKeyPem);
422
-
423
-		$shareKeys = $this->crypt->multiKeyEncrypt('content', ['user1' => $publicKey]);
424
-		$this->assertEquals(
425
-			'content',
426
-			$this->crypt->multiKeyDecrypt($shareKeys['user1'], $privateKey)
427
-		);
428
-	}
22
+    protected LoggerInterface&MockObject $logger;
23
+    protected IUserSession&MockObject $userSession;
24
+    protected IConfig&MockObject $config;
25
+    protected IL10N&MockObject $l;
26
+
27
+    protected Crypt $crypt;
28
+
29
+    protected function setUp(): void {
30
+        parent::setUp();
31
+
32
+        $this->logger = $this->getMockBuilder(LoggerInterface::class)
33
+            ->disableOriginalConstructor()
34
+            ->getMock();
35
+        $this->logger->expects($this->any())
36
+            ->method('warning');
37
+        $this->userSession = $this->getMockBuilder(IUserSession::class)
38
+            ->disableOriginalConstructor()
39
+            ->getMock();
40
+        $this->config = $this->getMockBuilder(IConfig::class)
41
+            ->disableOriginalConstructor()
42
+            ->getMock();
43
+        $this->l = $this->createMock(IL10N::class);
44
+
45
+        $this->crypt = new Crypt($this->logger, $this->userSession, $this->config, $this->l);
46
+    }
47
+
48
+    /**
49
+     * test getOpenSSLConfig without any additional parameters
50
+     */
51
+    public function testGetOpenSSLConfigBasic(): void {
52
+        $this->config->expects($this->once())
53
+            ->method('getSystemValue')
54
+            ->with($this->equalTo('openssl'), $this->equalTo([]))
55
+            ->willReturn([]);
56
+
57
+        $result = self::invokePrivate($this->crypt, 'getOpenSSLConfig');
58
+        $this->assertSame(1, count($result));
59
+        $this->assertArrayHasKey('private_key_bits', $result);
60
+        $this->assertSame(4096, $result['private_key_bits']);
61
+    }
62
+
63
+    /**
64
+     * test getOpenSSLConfig with additional parameters defined in config.php
65
+     */
66
+    public function testGetOpenSSLConfig(): void {
67
+        $this->config->expects($this->once())
68
+            ->method('getSystemValue')
69
+            ->with($this->equalTo('openssl'), $this->equalTo([]))
70
+            ->willReturn(['foo' => 'bar', 'private_key_bits' => 1028]);
71
+
72
+        $result = self::invokePrivate($this->crypt, 'getOpenSSLConfig');
73
+        $this->assertSame(2, count($result));
74
+        $this->assertArrayHasKey('private_key_bits', $result);
75
+        $this->assertArrayHasKey('foo', $result);
76
+        $this->assertSame(1028, $result['private_key_bits']);
77
+        $this->assertSame('bar', $result['foo']);
78
+    }
79
+
80
+
81
+    /**
82
+     * test generateHeader with valid key formats
83
+     */
84
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataTestGenerateHeader')]
85
+    public function testGenerateHeader($keyFormat, $expected): void {
86
+        $this->config->expects($this->once())
87
+            ->method('getSystemValueString')
88
+            ->with($this->equalTo('cipher'), $this->equalTo('AES-256-CTR'))
89
+            ->willReturn('AES-128-CFB');
90
+
91
+        if ($keyFormat) {
92
+            $result = $this->crypt->generateHeader($keyFormat);
93
+        } else {
94
+            $result = $this->crypt->generateHeader();
95
+        }
96
+
97
+        $this->assertSame($expected, $result);
98
+    }
99
+
100
+    /**
101
+     * test generateHeader with invalid key format
102
+     *
103
+     */
104
+    public function testGenerateHeaderInvalid(): void {
105
+        $this->expectException(\InvalidArgumentException::class);
106
+
107
+        $this->crypt->generateHeader('unknown');
108
+    }
109
+
110
+    public static function dataTestGenerateHeader(): array {
111
+        return [
112
+            [null, 'HBEGIN:cipher:AES-128-CFB:keyFormat:hash2:encoding:binary:HEND'],
113
+            ['password', 'HBEGIN:cipher:AES-128-CFB:keyFormat:password:encoding:binary:HEND'],
114
+            ['hash', 'HBEGIN:cipher:AES-128-CFB:keyFormat:hash:encoding:binary:HEND']
115
+        ];
116
+    }
117
+
118
+    public function testGetCipherWithInvalidCipher(): void {
119
+        $this->config->expects($this->once())
120
+            ->method('getSystemValueString')
121
+            ->with($this->equalTo('cipher'), $this->equalTo('AES-256-CTR'))
122
+            ->willReturn('Not-Existing-Cipher');
123
+        $this->logger
124
+            ->expects($this->once())
125
+            ->method('warning')
126
+            ->with('Unsupported cipher (Not-Existing-Cipher) defined in config.php supported. Falling back to AES-256-CTR');
127
+
128
+        $this->assertSame('AES-256-CTR', $this->crypt->getCipher());
129
+    }
130
+
131
+    /**
132
+     * @param string $configValue
133
+     * @param string $expected
134
+     */
135
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataProviderGetCipher')]
136
+    public function testGetCipher($configValue, $expected): void {
137
+        $this->config->expects($this->once())
138
+            ->method('getSystemValueString')
139
+            ->with($this->equalTo('cipher'), $this->equalTo('AES-256-CTR'))
140
+            ->willReturn($configValue);
141
+
142
+        $this->assertSame($expected,
143
+            $this->crypt->getCipher()
144
+        );
145
+    }
146
+
147
+    /**
148
+     * data provider for testGetCipher
149
+     */
150
+    public static function dataProviderGetCipher(): array {
151
+        return [
152
+            ['AES-128-CFB', 'AES-128-CFB'],
153
+            ['AES-256-CFB', 'AES-256-CFB'],
154
+            ['AES-128-CTR', 'AES-128-CTR'],
155
+            ['AES-256-CTR', 'AES-256-CTR'],
156
+
157
+            ['unknown', 'AES-256-CTR']
158
+        ];
159
+    }
160
+
161
+    /**
162
+     * test concatIV()
163
+     */
164
+    public function testConcatIV(): void {
165
+        $result = self::invokePrivate(
166
+            $this->crypt,
167
+            'concatIV',
168
+            ['content', 'my_iv']);
169
+
170
+        $this->assertSame('content00iv00my_iv',
171
+            $result
172
+        );
173
+    }
174
+
175
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataTestSplitMetaData')]
176
+    public function testSplitMetaData($data, $expected): void {
177
+        $this->config->method('getSystemValueBool')
178
+            ->with('encryption_skip_signature_check', false)
179
+            ->willReturn(true);
180
+        $result = self::invokePrivate($this->crypt, 'splitMetaData', [$data, 'AES-256-CFB']);
181
+        $this->assertTrue(is_array($result));
182
+        $this->assertSame(3, count($result));
183
+        $this->assertArrayHasKey('encrypted', $result);
184
+        $this->assertArrayHasKey('iv', $result);
185
+        $this->assertArrayHasKey('signature', $result);
186
+        $this->assertSame($expected['encrypted'], $result['encrypted']);
187
+        $this->assertSame($expected['iv'], $result['iv']);
188
+        $this->assertSame($expected['signature'], $result['signature']);
189
+    }
190
+
191
+    public static function dataTestSplitMetaData(): array {
192
+        return [
193
+            ['encryptedContent00iv001234567890123456xx',
194
+                ['encrypted' => 'encryptedContent', 'iv' => '1234567890123456', 'signature' => false]],
195
+            ['encryptedContent00iv00123456789012345600sig00e1992521e437f6915f9173b190a512cfc38a00ac24502db44e0ba10c2bb0cc86xxx',
196
+                ['encrypted' => 'encryptedContent', 'iv' => '1234567890123456', 'signature' => 'e1992521e437f6915f9173b190a512cfc38a00ac24502db44e0ba10c2bb0cc86']],
197
+        ];
198
+    }
199
+
200
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataTestHasSignature')]
201
+    public function testHasSignature($data, $expected): void {
202
+        $this->config->method('getSystemValueBool')
203
+            ->with('encryption_skip_signature_check', false)
204
+            ->willReturn(true);
205
+        $this->assertSame($expected,
206
+            $this->invokePrivate($this->crypt, 'hasSignature', [$data, 'AES-256-CFB'])
207
+        );
208
+    }
209
+
210
+    public static function dataTestHasSignature(): array {
211
+        return [
212
+            ['encryptedContent00iv001234567890123456xx', false],
213
+            ['encryptedContent00iv00123456789012345600sig00e1992521e437f6915f9173b190a512cfc38a00ac24502db44e0ba10c2bb0cc86xxx', true]
214
+        ];
215
+    }
216
+
217
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataTestHasSignatureFail')]
218
+    public function testHasSignatureFail($cipher): void {
219
+        $this->expectException(GenericEncryptionException::class);
220
+
221
+        $data = 'encryptedContent00iv001234567890123456xx';
222
+        $this->invokePrivate($this->crypt, 'hasSignature', [$data, $cipher]);
223
+    }
224
+
225
+    public static function dataTestHasSignatureFail(): array {
226
+        return [
227
+            ['AES-256-CTR'],
228
+            ['aes-256-ctr'],
229
+            ['AES-128-CTR'],
230
+            ['ctr-256-ctr']
231
+        ];
232
+    }
233
+
234
+    /**
235
+     * test addPadding()
236
+     */
237
+    public function testAddPadding(): void {
238
+        $result = self::invokePrivate($this->crypt, 'addPadding', ['data']);
239
+        $this->assertSame('dataxxx', $result);
240
+    }
241
+
242
+    /**
243
+     * test removePadding()
244
+     *
245
+     * @param $data
246
+     * @param $expected
247
+     */
248
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataProviderRemovePadding')]
249
+    public function testRemovePadding($data, $expected): void {
250
+        $result = self::invokePrivate($this->crypt, 'removePadding', [$data]);
251
+        $this->assertSame($expected, $result);
252
+    }
253
+
254
+    /**
255
+     * data provider for testRemovePadding
256
+     */
257
+    public static function dataProviderRemovePadding(): array {
258
+        return [
259
+            ['dataxx', 'data'],
260
+            ['data', false]
261
+        ];
262
+    }
263
+
264
+    /**
265
+     * test parseHeader()
266
+     */
267
+    public function testParseHeader(): void {
268
+        $header = 'HBEGIN:foo:bar:cipher:AES-256-CFB:encoding:binary:HEND';
269
+        $result = self::invokePrivate($this->crypt, 'parseHeader', [$header]);
270
+
271
+        $this->assertTrue(is_array($result));
272
+        $this->assertSame(3, count($result));
273
+        $this->assertArrayHasKey('foo', $result);
274
+        $this->assertArrayHasKey('cipher', $result);
275
+        $this->assertArrayHasKey('encoding', $result);
276
+        $this->assertSame('bar', $result['foo']);
277
+        $this->assertSame('AES-256-CFB', $result['cipher']);
278
+        $this->assertSame('binary', $result['encoding']);
279
+    }
280
+
281
+    /**
282
+     * test encrypt()
283
+     *
284
+     * @return string
285
+     */
286
+    public function testEncrypt() {
287
+        $decrypted = 'content';
288
+        $password = 'password';
289
+        $cipher = 'AES-256-CTR';
290
+        $iv = self::invokePrivate($this->crypt, 'generateIv');
291
+
292
+        $this->assertTrue(is_string($iv));
293
+        $this->assertSame(16, strlen($iv));
294
+
295
+        $result = self::invokePrivate($this->crypt, 'encrypt', [$decrypted, $iv, $password, $cipher]);
296
+
297
+        $this->assertTrue(is_string($result));
298
+
299
+        return [
300
+            'password' => $password,
301
+            'iv' => $iv,
302
+            'cipher' => $cipher,
303
+            'encrypted' => $result,
304
+            'decrypted' => $decrypted];
305
+    }
306
+
307
+    /**
308
+     * test decrypt()
309
+     *
310
+     * @depends testEncrypt
311
+     */
312
+    public function testDecrypt($data): void {
313
+        $result = self::invokePrivate(
314
+            $this->crypt,
315
+            'decrypt',
316
+            [$data['encrypted'], $data['iv'], $data['password'], $data['cipher'], true]);
317
+
318
+        $this->assertSame($data['decrypted'], $result);
319
+    }
320
+
321
+    /**
322
+     * test return values of valid ciphers
323
+     */
324
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataTestGetKeySize')]
325
+    public function testGetKeySize($cipher, $expected): void {
326
+        $result = $this->invokePrivate($this->crypt, 'getKeySize', [$cipher]);
327
+        $this->assertSame($expected, $result);
328
+    }
329
+
330
+    /**
331
+     * test exception if cipher is unknown
332
+     *
333
+     */
334
+    public function testGetKeySizeFailure(): void {
335
+        $this->expectException(\InvalidArgumentException::class);
336
+
337
+        $this->invokePrivate($this->crypt, 'getKeySize', ['foo']);
338
+    }
339
+
340
+    public static function dataTestGetKeySize(): array {
341
+        return [
342
+            ['AES-256-CFB', 32],
343
+            ['AES-128-CFB', 16],
344
+            ['AES-256-CTR', 32],
345
+            ['AES-128-CTR', 16],
346
+        ];
347
+    }
348
+
349
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataTestDecryptPrivateKey')]
350
+    public function testDecryptPrivateKey($header, $privateKey, $expectedCipher, $isValidKey, $expected): void {
351
+        $this->config->method('getSystemValueBool')
352
+            ->willReturnMap([
353
+                ['encryption.legacy_format_support', false, true],
354
+                ['encryption.use_legacy_base64_encoding', false, false],
355
+            ]);
356
+
357
+        /** @var Crypt|\PHPUnit\Framework\MockObject\MockObject $crypt */
358
+        $crypt = $this->getMockBuilder(Crypt::class)
359
+            ->setConstructorArgs([
360
+                $this->logger,
361
+                $this->userSession,
362
+                $this->config,
363
+                $this->l
364
+            ])
365
+            ->onlyMethods([
366
+                'parseHeader',
367
+                'generatePasswordHash',
368
+                'symmetricDecryptFileContent',
369
+                'isValidPrivateKey'
370
+            ])
371
+            ->getMock();
372
+
373
+        $crypt->expects($this->once())->method('parseHeader')->willReturn($header);
374
+        if (isset($header['keyFormat']) && $header['keyFormat'] === 'hash') {
375
+            $crypt->expects($this->once())->method('generatePasswordHash')->willReturn('hash');
376
+            $password = 'hash';
377
+        } else {
378
+            $crypt->expects($this->never())->method('generatePasswordHash');
379
+            $password = 'password';
380
+        }
381
+
382
+        $crypt->expects($this->once())->method('symmetricDecryptFileContent')
383
+            ->with('privateKey', $password, $expectedCipher)->willReturn('key');
384
+        $crypt->expects($this->once())->method('isValidPrivateKey')->willReturn($isValidKey);
385
+
386
+        $result = $crypt->decryptPrivateKey($privateKey, 'password');
387
+
388
+        $this->assertSame($expected, $result);
389
+    }
390
+
391
+    public static function dataTestDecryptPrivateKey(): array {
392
+        return [
393
+            [['cipher' => 'AES-128-CFB', 'keyFormat' => 'password'], 'HBEGIN:HENDprivateKey', 'AES-128-CFB', true, 'key'],
394
+            [['cipher' => 'AES-256-CFB', 'keyFormat' => 'password'], 'HBEGIN:HENDprivateKey', 'AES-256-CFB', true, 'key'],
395
+            [['cipher' => 'AES-256-CFB', 'keyFormat' => 'password'], 'HBEGIN:HENDprivateKey', 'AES-256-CFB', false, false],
396
+            [['cipher' => 'AES-256-CFB', 'keyFormat' => 'hash'], 'HBEGIN:HENDprivateKey', 'AES-256-CFB', true, 'key'],
397
+            [['cipher' => 'AES-256-CFB'], 'HBEGIN:HENDprivateKey', 'AES-256-CFB', true, 'key'],
398
+            [[], 'privateKey', 'AES-128-CFB', true, 'key'],
399
+        ];
400
+    }
401
+
402
+    public function testIsValidPrivateKey(): void {
403
+        $res = openssl_pkey_new();
404
+        openssl_pkey_export($res, $privateKey);
405
+
406
+        // valid private key
407
+        $this->assertTrue(
408
+            $this->invokePrivate($this->crypt, 'isValidPrivateKey', [$privateKey])
409
+        );
410
+
411
+        // invalid private key
412
+        $this->assertFalse(
413
+            $this->invokePrivate($this->crypt, 'isValidPrivateKey', ['foo'])
414
+        );
415
+    }
416
+
417
+    public function testMultiKeyEncrypt(): void {
418
+        $res = openssl_pkey_new();
419
+        openssl_pkey_export($res, $privateKey);
420
+        $publicKeyPem = openssl_pkey_get_details($res)['key'];
421
+        $publicKey = openssl_pkey_get_public($publicKeyPem);
422
+
423
+        $shareKeys = $this->crypt->multiKeyEncrypt('content', ['user1' => $publicKey]);
424
+        $this->assertEquals(
425
+            'content',
426
+            $this->crypt->multiKeyDecrypt($shareKeys['user1'], $privateKey)
427
+        );
428
+    }
429 429
 }
Please login to merge, or discard this patch.
apps/encryption/tests/Settings/AdminTest.php 2 patches
Indentation   +51 added lines, -51 removed lines patch added patch discarded remove patch
@@ -21,62 +21,62 @@
 block discarded – undo
21 21
 
22 22
 class AdminTest extends TestCase {
23 23
 
24
-	protected Admin $admin;
24
+    protected Admin $admin;
25 25
 
26
-	protected IL10N&MockObject $l;
27
-	protected LoggerInterface&MockObject $logger;
28
-	protected IUserSession&MockObject $userSession;
29
-	protected IConfig&MockObject $config;
30
-	protected IUserManager&MockObject $userManager;
31
-	protected ISession&MockObject $session;
26
+    protected IL10N&MockObject $l;
27
+    protected LoggerInterface&MockObject $logger;
28
+    protected IUserSession&MockObject $userSession;
29
+    protected IConfig&MockObject $config;
30
+    protected IUserManager&MockObject $userManager;
31
+    protected ISession&MockObject $session;
32 32
 
33
-	protected function setUp(): void {
34
-		parent::setUp();
33
+    protected function setUp(): void {
34
+        parent::setUp();
35 35
 
36
-		$this->l = $this->getMockBuilder(IL10N::class)->getMock();
37
-		$this->logger = $this->getMockBuilder(LoggerInterface::class)->getMock();
38
-		$this->userSession = $this->getMockBuilder(IUserSession::class)->getMock();
39
-		$this->config = $this->getMockBuilder(IConfig::class)->getMock();
40
-		$this->userManager = $this->getMockBuilder(IUserManager::class)->getMock();
41
-		$this->session = $this->getMockBuilder(ISession::class)->getMock();
36
+        $this->l = $this->getMockBuilder(IL10N::class)->getMock();
37
+        $this->logger = $this->getMockBuilder(LoggerInterface::class)->getMock();
38
+        $this->userSession = $this->getMockBuilder(IUserSession::class)->getMock();
39
+        $this->config = $this->getMockBuilder(IConfig::class)->getMock();
40
+        $this->userManager = $this->getMockBuilder(IUserManager::class)->getMock();
41
+        $this->session = $this->getMockBuilder(ISession::class)->getMock();
42 42
 
43
-		$this->admin = new Admin(
44
-			$this->l,
45
-			$this->logger,
46
-			$this->userSession,
47
-			$this->config,
48
-			$this->userManager,
49
-			$this->session
50
-		);
51
-	}
43
+        $this->admin = new Admin(
44
+            $this->l,
45
+            $this->logger,
46
+            $this->userSession,
47
+            $this->config,
48
+            $this->userManager,
49
+            $this->session
50
+        );
51
+    }
52 52
 
53
-	public function testGetForm(): void {
54
-		$this->config
55
-			->method('getAppValue')
56
-			->willReturnCallback(function ($app, $key, $default) {
57
-				if ($app === 'encryption' && $key === 'recoveryAdminEnabled' && $default === '0') {
58
-					return '1';
59
-				}
60
-				if ($app === 'encryption' && $key === 'encryptHomeStorage' && $default === '1') {
61
-					return '1';
62
-				}
63
-				return $default;
64
-			});
65
-		$params = [
66
-			'recoveryEnabled' => '1',
67
-			'initStatus' => '0',
68
-			'encryptHomeStorage' => true,
69
-			'masterKeyEnabled' => true
70
-		];
71
-		$expected = new TemplateResponse('encryption', 'settings-admin', $params, '');
72
-		$this->assertEquals($expected, $this->admin->getForm());
73
-	}
53
+    public function testGetForm(): void {
54
+        $this->config
55
+            ->method('getAppValue')
56
+            ->willReturnCallback(function ($app, $key, $default) {
57
+                if ($app === 'encryption' && $key === 'recoveryAdminEnabled' && $default === '0') {
58
+                    return '1';
59
+                }
60
+                if ($app === 'encryption' && $key === 'encryptHomeStorage' && $default === '1') {
61
+                    return '1';
62
+                }
63
+                return $default;
64
+            });
65
+        $params = [
66
+            'recoveryEnabled' => '1',
67
+            'initStatus' => '0',
68
+            'encryptHomeStorage' => true,
69
+            'masterKeyEnabled' => true
70
+        ];
71
+        $expected = new TemplateResponse('encryption', 'settings-admin', $params, '');
72
+        $this->assertEquals($expected, $this->admin->getForm());
73
+    }
74 74
 
75
-	public function testGetSection(): void {
76
-		$this->assertSame('security', $this->admin->getSection());
77
-	}
75
+    public function testGetSection(): void {
76
+        $this->assertSame('security', $this->admin->getSection());
77
+    }
78 78
 
79
-	public function testGetPriority(): void {
80
-		$this->assertSame(11, $this->admin->getPriority());
81
-	}
79
+    public function testGetPriority(): void {
80
+        $this->assertSame(11, $this->admin->getPriority());
81
+    }
82 82
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -53,7 +53,7 @@
 block discarded – undo
53 53
 	public function testGetForm(): void {
54 54
 		$this->config
55 55
 			->method('getAppValue')
56
-			->willReturnCallback(function ($app, $key, $default) {
56
+			->willReturnCallback(function($app, $key, $default) {
57 57
 				if ($app === 'encryption' && $key === 'recoveryAdminEnabled' && $default === '0') {
58 58
 					return '1';
59 59
 				}
Please login to merge, or discard this patch.
apps/encryption/tests/Users/SetupTest.php 1 patch
Indentation   +57 added lines, -57 removed lines patch added patch discarded remove patch
@@ -17,61 +17,61 @@
 block discarded – undo
17 17
 
18 18
 class SetupTest extends TestCase {
19 19
 
20
-	protected Setup $instance;
21
-
22
-	protected KeyManager&MockObject $keyManagerMock;
23
-	protected Crypt&MockObject $cryptMock;
24
-
25
-	protected function setUp(): void {
26
-		parent::setUp();
27
-		$this->cryptMock = $this->getMockBuilder(Crypt::class)
28
-			->disableOriginalConstructor()
29
-			->getMock();
30
-
31
-		$this->keyManagerMock = $this->getMockBuilder(KeyManager::class)
32
-			->disableOriginalConstructor()
33
-			->getMock();
34
-
35
-		$this->instance = new Setup(
36
-			$this->cryptMock,
37
-			$this->keyManagerMock);
38
-	}
39
-
40
-
41
-	public function testSetupSystem(): void {
42
-		$this->keyManagerMock->expects($this->once())->method('validateShareKey');
43
-		$this->keyManagerMock->expects($this->once())->method('validateMasterKey');
44
-
45
-		$this->instance->setupSystem();
46
-	}
47
-
48
-	/**
49
-	 *
50
-	 * @param bool $hasKeys
51
-	 * @param bool $expected
52
-	 */
53
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataTestSetupUser')]
54
-	public function testSetupUser($hasKeys, $expected): void {
55
-		$this->keyManagerMock->expects($this->once())->method('userHasKeys')
56
-			->with('uid')->willReturn($hasKeys);
57
-
58
-		if ($hasKeys) {
59
-			$this->keyManagerMock->expects($this->never())->method('storeKeyPair');
60
-		} else {
61
-			$this->cryptMock->expects($this->once())->method('createKeyPair')->willReturn(['publicKey' => 'publicKey', 'privateKey' => 'privateKey']);
62
-			$this->keyManagerMock->expects($this->once())->method('storeKeyPair')
63
-				->with('uid', 'password', ['publicKey' => 'publicKey', 'privateKey' => 'privateKey'])->willReturn(true);
64
-		}
65
-
66
-		$this->assertSame($expected,
67
-			$this->instance->setupUser('uid', 'password')
68
-		);
69
-	}
70
-
71
-	public static function dataTestSetupUser(): array {
72
-		return [
73
-			[true, true],
74
-			[false, true]
75
-		];
76
-	}
20
+    protected Setup $instance;
21
+
22
+    protected KeyManager&MockObject $keyManagerMock;
23
+    protected Crypt&MockObject $cryptMock;
24
+
25
+    protected function setUp(): void {
26
+        parent::setUp();
27
+        $this->cryptMock = $this->getMockBuilder(Crypt::class)
28
+            ->disableOriginalConstructor()
29
+            ->getMock();
30
+
31
+        $this->keyManagerMock = $this->getMockBuilder(KeyManager::class)
32
+            ->disableOriginalConstructor()
33
+            ->getMock();
34
+
35
+        $this->instance = new Setup(
36
+            $this->cryptMock,
37
+            $this->keyManagerMock);
38
+    }
39
+
40
+
41
+    public function testSetupSystem(): void {
42
+        $this->keyManagerMock->expects($this->once())->method('validateShareKey');
43
+        $this->keyManagerMock->expects($this->once())->method('validateMasterKey');
44
+
45
+        $this->instance->setupSystem();
46
+    }
47
+
48
+    /**
49
+     *
50
+     * @param bool $hasKeys
51
+     * @param bool $expected
52
+     */
53
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataTestSetupUser')]
54
+    public function testSetupUser($hasKeys, $expected): void {
55
+        $this->keyManagerMock->expects($this->once())->method('userHasKeys')
56
+            ->with('uid')->willReturn($hasKeys);
57
+
58
+        if ($hasKeys) {
59
+            $this->keyManagerMock->expects($this->never())->method('storeKeyPair');
60
+        } else {
61
+            $this->cryptMock->expects($this->once())->method('createKeyPair')->willReturn(['publicKey' => 'publicKey', 'privateKey' => 'privateKey']);
62
+            $this->keyManagerMock->expects($this->once())->method('storeKeyPair')
63
+                ->with('uid', 'password', ['publicKey' => 'publicKey', 'privateKey' => 'privateKey'])->willReturn(true);
64
+        }
65
+
66
+        $this->assertSame($expected,
67
+            $this->instance->setupUser('uid', 'password')
68
+        );
69
+    }
70
+
71
+    public static function dataTestSetupUser(): array {
72
+        return [
73
+            [true, true],
74
+            [false, true]
75
+        ];
76
+    }
77 77
 }
Please login to merge, or discard this patch.
apps/encryption/tests/KeyManagerTest.php 2 patches
Indentation   +674 added lines, -674 removed lines patch added patch discarded remove patch
@@ -31,678 +31,678 @@
 block discarded – undo
31 31
 
32 32
 class KeyManagerTest extends TestCase {
33 33
 
34
-	protected KeyManager $instance;
35
-
36
-	protected string $userId;
37
-	protected string $systemKeyId;
38
-	protected IStorage&MockObject $keyStorageMock;
39
-	protected Crypt&MockObject $cryptMock;
40
-	protected IUserSession&MockObject $userMock;
41
-	protected Session&MockObject $sessionMock;
42
-	protected LoggerInterface&MockObject $logMock;
43
-	protected Util&MockObject $utilMock;
44
-	protected IConfig&MockObject $configMock;
45
-	protected ILockingProvider&MockObject $lockingProviderMock;
46
-
47
-	protected function setUp(): void {
48
-		parent::setUp();
49
-		$this->userId = 'user1';
50
-		$this->systemKeyId = 'systemKeyId';
51
-		$this->keyStorageMock = $this->createMock(IStorage::class);
52
-		$this->cryptMock = $this->getMockBuilder(Crypt::class)
53
-			->disableOriginalConstructor()
54
-			->getMock();
55
-		$this->configMock = $this->createMock(IConfig::class);
56
-		$this->configMock->expects($this->any())
57
-			->method('getAppValue')
58
-			->willReturn($this->systemKeyId);
59
-		$this->userMock = $this->createMock(IUserSession::class);
60
-		$this->sessionMock = $this->getMockBuilder(Session::class)
61
-			->disableOriginalConstructor()
62
-			->getMock();
63
-		$this->logMock = $this->createMock(LoggerInterface::class);
64
-		$this->utilMock = $this->getMockBuilder(Util::class)
65
-			->disableOriginalConstructor()
66
-			->getMock();
67
-		$this->lockingProviderMock = $this->createMock(ILockingProvider::class);
68
-
69
-		$this->instance = new KeyManager(
70
-			$this->keyStorageMock,
71
-			$this->cryptMock,
72
-			$this->configMock,
73
-			$this->userMock,
74
-			$this->sessionMock,
75
-			$this->logMock,
76
-			$this->utilMock,
77
-			$this->lockingProviderMock
78
-		);
79
-	}
80
-
81
-	public function testDeleteShareKey(): void {
82
-		$this->keyStorageMock->expects($this->any())
83
-			->method('deleteFileKey')
84
-			->with($this->equalTo('/path'), $this->equalTo('keyId.shareKey'))
85
-			->willReturn(true);
86
-
87
-		$this->assertTrue(
88
-			$this->instance->deleteShareKey('/path', 'keyId')
89
-		);
90
-	}
91
-
92
-	public function testGetPrivateKey(): void {
93
-		$this->keyStorageMock->expects($this->any())
94
-			->method('getUserKey')
95
-			->with($this->equalTo($this->userId), $this->equalTo('privateKey'))
96
-			->willReturn('privateKey');
97
-
98
-
99
-		$this->assertSame('privateKey',
100
-			$this->instance->getPrivateKey($this->userId)
101
-		);
102
-	}
103
-
104
-	public function testGetPublicKey(): void {
105
-		$this->keyStorageMock->expects($this->any())
106
-			->method('getUserKey')
107
-			->with($this->equalTo($this->userId), $this->equalTo('publicKey'))
108
-			->willReturn('publicKey');
109
-
110
-
111
-		$this->assertSame('publicKey',
112
-			$this->instance->getPublicKey($this->userId)
113
-		);
114
-	}
115
-
116
-	public function testRecoveryKeyExists(): void {
117
-		$this->keyStorageMock->expects($this->any())
118
-			->method('getSystemUserKey')
119
-			->with($this->equalTo($this->systemKeyId . '.publicKey'))
120
-			->willReturn('recoveryKey');
121
-
122
-
123
-		$this->assertTrue($this->instance->recoveryKeyExists());
124
-	}
125
-
126
-	public function testCheckRecoveryKeyPassword(): void {
127
-		$this->keyStorageMock->expects($this->any())
128
-			->method('getSystemUserKey')
129
-			->with($this->equalTo($this->systemKeyId . '.privateKey'))
130
-			->willReturn('recoveryKey');
131
-		$this->cryptMock->expects($this->any())
132
-			->method('decryptPrivateKey')
133
-			->with($this->equalTo('recoveryKey'), $this->equalTo('pass'))
134
-			->willReturn('decryptedRecoveryKey');
135
-
136
-		$this->assertTrue($this->instance->checkRecoveryPassword('pass'));
137
-	}
138
-
139
-	public function testSetPublicKey(): void {
140
-		$this->keyStorageMock->expects($this->any())
141
-			->method('setUserKey')
142
-			->with(
143
-				$this->equalTo($this->userId),
144
-				$this->equalTo('publicKey'),
145
-				$this->equalTo('key'))
146
-			->willReturn(true);
147
-
148
-
149
-		$this->assertTrue(
150
-			$this->instance->setPublicKey($this->userId, 'key')
151
-		);
152
-	}
153
-
154
-	public function testSetPrivateKey(): void {
155
-		$this->keyStorageMock->expects($this->any())
156
-			->method('setUserKey')
157
-			->with(
158
-				$this->equalTo($this->userId),
159
-				$this->equalTo('privateKey'),
160
-				$this->equalTo('key'))
161
-			->willReturn(true);
162
-
163
-
164
-		$this->assertTrue(
165
-			$this->instance->setPrivateKey($this->userId, 'key')
166
-		);
167
-	}
168
-
169
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataTestUserHasKeys')]
170
-	public function testUserHasKeys($key, $expected): void {
171
-		$this->keyStorageMock->expects($this->exactly(2))
172
-			->method('getUserKey')
173
-			->with($this->equalTo($this->userId), $this->anything())
174
-			->willReturn($key);
175
-
176
-
177
-		$this->assertSame($expected,
178
-			$this->instance->userHasKeys($this->userId)
179
-		);
180
-	}
181
-
182
-	public static function dataTestUserHasKeys(): array {
183
-		return [
184
-			['key', true],
185
-			['', false]
186
-		];
187
-	}
188
-
189
-
190
-	public function testUserHasKeysMissingPrivateKey(): void {
191
-		$this->expectException(PrivateKeyMissingException::class);
192
-
193
-		$this->keyStorageMock->expects($this->exactly(2))
194
-			->method('getUserKey')
195
-			->willReturnCallback(function ($uid, $keyID, $encryptionModuleId) {
196
-				if ($keyID === 'privateKey') {
197
-					return '';
198
-				}
199
-				return 'key';
200
-			});
201
-
202
-		$this->instance->userHasKeys($this->userId);
203
-	}
204
-
205
-
206
-	public function testUserHasKeysMissingPublicKey(): void {
207
-		$this->expectException(PublicKeyMissingException::class);
208
-
209
-		$this->keyStorageMock->expects($this->exactly(2))
210
-			->method('getUserKey')
211
-			->willReturnCallback(function ($uid, $keyID, $encryptionModuleId) {
212
-				if ($keyID === 'publicKey') {
213
-					return '';
214
-				}
215
-				return 'key';
216
-			});
217
-
218
-		$this->instance->userHasKeys($this->userId);
219
-	}
220
-
221
-	/**
222
-	 * @param bool $useMasterKey
223
-	 */
224
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataTestInit')]
225
-	public function testInit($useMasterKey): void {
226
-		/** @var KeyManager&MockObject $instance */
227
-		$instance = $this->getMockBuilder(KeyManager::class)
228
-			->setConstructorArgs(
229
-				[
230
-					$this->keyStorageMock,
231
-					$this->cryptMock,
232
-					$this->configMock,
233
-					$this->userMock,
234
-					$this->sessionMock,
235
-					$this->logMock,
236
-					$this->utilMock,
237
-					$this->lockingProviderMock
238
-				]
239
-			)->onlyMethods(['getMasterKeyId', 'getMasterKeyPassword', 'getSystemPrivateKey', 'getPrivateKey'])
240
-			->getMock();
241
-
242
-		$this->utilMock->expects($this->once())->method('isMasterKeyEnabled')
243
-			->willReturn($useMasterKey);
244
-
245
-		$sessionSetStatusCalls = [];
246
-		$this->sessionMock->expects($this->exactly(2))
247
-			->method('setStatus')
248
-			->willReturnCallback(function (string $status) use (&$sessionSetStatusCalls): void {
249
-				$sessionSetStatusCalls[] = $status;
250
-			});
251
-
252
-		$instance->expects($this->any())->method('getMasterKeyId')->willReturn('masterKeyId');
253
-		$instance->expects($this->any())->method('getMasterKeyPassword')->willReturn('masterKeyPassword');
254
-		$instance->expects($this->any())->method('getSystemPrivateKey')->with('masterKeyId')->willReturn('privateMasterKey');
255
-		$instance->expects($this->any())->method('getPrivateKey')->with($this->userId)->willReturn('privateUserKey');
256
-
257
-		if ($useMasterKey) {
258
-			$this->cryptMock->expects($this->once())->method('decryptPrivateKey')
259
-				->with('privateMasterKey', 'masterKeyPassword', 'masterKeyId')
260
-				->willReturn('key');
261
-		} else {
262
-			$this->cryptMock->expects($this->once())->method('decryptPrivateKey')
263
-				->with('privateUserKey', 'pass', $this->userId)
264
-				->willReturn('key');
265
-		}
266
-
267
-		$this->sessionMock->expects($this->once())->method('setPrivateKey')
268
-			->with('key');
269
-
270
-		$this->assertTrue($instance->init($this->userId, 'pass'));
271
-		self::assertEquals([
272
-			Session::INIT_EXECUTED,
273
-			Session::INIT_SUCCESSFUL,
274
-		], $sessionSetStatusCalls);
275
-	}
276
-
277
-	public static function dataTestInit(): array {
278
-		return [
279
-			[true],
280
-			[false]
281
-		];
282
-	}
283
-
284
-
285
-	public function testSetRecoveryKey(): void {
286
-		$this->keyStorageMock->expects($this->exactly(2))
287
-			->method('setSystemUserKey')
288
-			->willReturn(true);
289
-		$this->cryptMock->expects($this->any())
290
-			->method('encryptPrivateKey')
291
-			->with($this->equalTo('privateKey'), $this->equalTo('pass'))
292
-			->willReturn('decryptedPrivateKey');
293
-
294
-
295
-		$this->assertTrue(
296
-			$this->instance->setRecoveryKey('pass',
297
-				['publicKey' => 'publicKey', 'privateKey' => 'privateKey'])
298
-		);
299
-	}
300
-
301
-	public function testSetSystemPrivateKey(): void {
302
-		$this->keyStorageMock->expects($this->exactly(1))
303
-			->method('setSystemUserKey')
304
-			->with($this->equalTo('keyId.privateKey'), $this->equalTo('key'))
305
-			->willReturn(true);
306
-
307
-
308
-		$this->assertTrue(
309
-			$this->instance->setSystemPrivateKey('keyId', 'key')
310
-		);
311
-	}
312
-
313
-	public function testGetSystemPrivateKey(): void {
314
-		$this->keyStorageMock->expects($this->exactly(1))
315
-			->method('getSystemUserKey')
316
-			->with($this->equalTo('keyId.privateKey'))
317
-			->willReturn('systemPrivateKey');
318
-
319
-
320
-		$this->assertSame('systemPrivateKey',
321
-			$this->instance->getSystemPrivateKey('keyId')
322
-		);
323
-	}
324
-
325
-	public function testGetEncryptedFileKey(): void {
326
-		$this->keyStorageMock->expects($this->once())
327
-			->method('getFileKey')
328
-			->with('/', 'fileKey')
329
-			->willReturn(true);
330
-
331
-		$this->assertTrue($this->instance->getEncryptedFileKey('/'));
332
-	}
333
-
334
-	public static function dataTestGetFileKey(): array {
335
-		return [
336
-			['user1', false, 'privateKey', 'legacyKey', 'multiKeyDecryptResult'],
337
-			['user1', false, 'privateKey', '', 'multiKeyDecryptResult'],
338
-			['user1', false, false, 'legacyKey', ''],
339
-			['user1', false, false, '', ''],
340
-			['user1', true, 'privateKey', 'legacyKey', 'multiKeyDecryptResult'],
341
-			['user1', true, 'privateKey', '', 'multiKeyDecryptResult'],
342
-			['user1', true, false, 'legacyKey', ''],
343
-			['user1', true, false, '', ''],
344
-			[null, false, 'privateKey', 'legacyKey', 'multiKeyDecryptResult'],
345
-			[null, false, 'privateKey', '', 'multiKeyDecryptResult'],
346
-			[null, false, false, 'legacyKey', ''],
347
-			[null, false, false, '', ''],
348
-			[null, true, 'privateKey', 'legacyKey', 'multiKeyDecryptResult'],
349
-			[null, true, 'privateKey', '', 'multiKeyDecryptResult'],
350
-			[null, true, false, 'legacyKey', ''],
351
-			[null, true, false, '', ''],
352
-		];
353
-	}
354
-
355
-	/**
356
-	 *
357
-	 * @param $uid
358
-	 * @param $isMasterKeyEnabled
359
-	 * @param $privateKey
360
-	 * @param $expected
361
-	 */
362
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataTestGetFileKey')]
363
-	public function testGetFileKey($uid, $isMasterKeyEnabled, $privateKey, $encryptedFileKey, $expected): void {
364
-		$path = '/foo.txt';
365
-
366
-		if ($isMasterKeyEnabled) {
367
-			$expectedUid = 'masterKeyId';
368
-			$this->configMock->expects($this->any())->method('getSystemValue')->with('secret')
369
-				->willReturn('password');
370
-		} elseif (!$uid) {
371
-			$expectedUid = 'systemKeyId';
372
-		} else {
373
-			$expectedUid = $uid;
374
-		}
375
-
376
-		$this->invokePrivate($this->instance, 'masterKeyId', ['masterKeyId']);
377
-
378
-		$this->keyStorageMock->expects($this->exactly(2))
379
-			->method('getFileKey')
380
-			->willReturnMap([
381
-				[$path, 'fileKey', 'OC_DEFAULT_MODULE', $encryptedFileKey],
382
-				[$path, $expectedUid . '.shareKey', 'OC_DEFAULT_MODULE', 'fileKey'],
383
-			]);
384
-
385
-		$this->utilMock->expects($this->any())->method('isMasterKeyEnabled')
386
-			->willReturn($isMasterKeyEnabled);
387
-
388
-		if (is_null($uid)) {
389
-			$this->keyStorageMock->expects($this->once())
390
-				->method('getSystemUserKey')
391
-				->willReturn(true);
392
-			$this->cryptMock->expects($this->once())
393
-				->method('decryptPrivateKey')
394
-				->willReturn($privateKey);
395
-		} else {
396
-			$this->keyStorageMock->expects($this->never())
397
-				->method('getSystemUserKey');
398
-			$this->sessionMock->expects($this->once())->method('getPrivateKey')->willReturn($privateKey);
399
-		}
400
-
401
-		if (!empty($encryptedFileKey)) {
402
-			$this->cryptMock->expects($this->never())
403
-				->method('multiKeyDecrypt');
404
-			if ($privateKey) {
405
-				$this->cryptMock->expects($this->once())
406
-					->method('multiKeyDecryptLegacy')
407
-					->willReturn('multiKeyDecryptResult');
408
-			} else {
409
-				$this->cryptMock->expects($this->never())
410
-					->method('multiKeyDecryptLegacy');
411
-			}
412
-		} else {
413
-			$this->cryptMock->expects($this->never())
414
-				->method('multiKeyDecryptLegacy');
415
-			if ($privateKey) {
416
-				$this->cryptMock->expects($this->once())
417
-					->method('multiKeyDecrypt')
418
-					->willReturn('multiKeyDecryptResult');
419
-			} else {
420
-				$this->cryptMock->expects($this->never())
421
-					->method('multiKeyDecrypt');
422
-			}
423
-		}
424
-
425
-		$this->assertSame($expected,
426
-			$this->instance->getFileKey($path, $uid, null)
427
-		);
428
-	}
429
-
430
-	public function testDeletePrivateKey(): void {
431
-		$this->keyStorageMock->expects($this->once())
432
-			->method('deleteUserKey')
433
-			->with('user1', 'privateKey')
434
-			->willReturn(true);
435
-
436
-		$this->assertTrue(self::invokePrivate($this->instance,
437
-			'deletePrivateKey',
438
-			[$this->userId]));
439
-	}
440
-
441
-	public function testDeleteAllFileKeys(): void {
442
-		$this->keyStorageMock->expects($this->once())
443
-			->method('deleteAllFileKeys')
444
-			->willReturn(true);
445
-
446
-		$this->assertTrue($this->instance->deleteAllFileKeys('/'));
447
-	}
448
-
449
-	/**
450
-	 * test add public share key and or recovery key to the list of public keys
451
-	 *
452
-	 *
453
-	 * @param array $accessList
454
-	 * @param array $publicKeys
455
-	 * @param string $uid
456
-	 * @param array $expectedKeys
457
-	 */
458
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataTestAddSystemKeys')]
459
-	public function testAddSystemKeys($accessList, $publicKeys, $uid, $expectedKeys): void {
460
-		$publicShareKeyId = 'publicShareKey';
461
-		$recoveryKeyId = 'recoveryKey';
462
-
463
-		$this->keyStorageMock->expects($this->any())
464
-			->method('getSystemUserKey')
465
-			->willReturnCallback(function ($keyId, $encryptionModuleId) {
466
-				return $keyId;
467
-			});
468
-
469
-		$this->utilMock->expects($this->any())
470
-			->method('isRecoveryEnabledForUser')
471
-			->willReturnCallback(function ($uid) {
472
-				if ($uid === 'user1') {
473
-					return true;
474
-				}
475
-				return false;
476
-			});
477
-
478
-		// set key IDs
479
-		self::invokePrivate($this->instance, 'publicShareKeyId', [$publicShareKeyId]);
480
-		self::invokePrivate($this->instance, 'recoveryKeyId', [$recoveryKeyId]);
481
-
482
-		$result = $this->instance->addSystemKeys($accessList, $publicKeys, $uid);
483
-
484
-		foreach ($expectedKeys as $expected) {
485
-			$this->assertArrayHasKey($expected, $result);
486
-		}
487
-
488
-		$this->assertSameSize($expectedKeys, $result);
489
-	}
490
-
491
-	/**
492
-	 * data provider for testAddSystemKeys()
493
-	 *
494
-	 * @return array
495
-	 */
496
-	public static function dataTestAddSystemKeys(): array {
497
-		return [
498
-			[['public' => true],[], 'user1', ['publicShareKey', 'recoveryKey']],
499
-			[['public' => false], [], 'user1', ['recoveryKey']],
500
-			[['public' => true],[], 'user2', ['publicShareKey']],
501
-			[['public' => false], [], 'user2', []],
502
-		];
503
-	}
504
-
505
-	public function testGetMasterKeyId(): void {
506
-		$this->assertSame('systemKeyId', $this->instance->getMasterKeyId());
507
-	}
508
-
509
-	public function testGetPublicMasterKey(): void {
510
-		$this->keyStorageMock->expects($this->once())->method('getSystemUserKey')
511
-			->with('systemKeyId.publicKey', Encryption::ID)
512
-			->willReturn(true);
513
-
514
-		$this->assertTrue(
515
-			$this->instance->getPublicMasterKey()
516
-		);
517
-	}
518
-
519
-	public function testGetMasterKeyPassword(): void {
520
-		$this->configMock->expects($this->once())->method('getSystemValue')->with('secret')
521
-			->willReturn('password');
522
-
523
-		$this->assertSame('password',
524
-			$this->invokePrivate($this->instance, 'getMasterKeyPassword', [])
525
-		);
526
-	}
527
-
528
-
529
-	public function testGetMasterKeyPasswordException(): void {
530
-		$this->expectException(\Exception::class);
531
-
532
-		$this->configMock->expects($this->once())->method('getSystemValue')->with('secret')
533
-			->willReturn('');
534
-
535
-		$this->invokePrivate($this->instance, 'getMasterKeyPassword', []);
536
-	}
537
-
538
-	/**
539
-	 * @param $masterKey
540
-	 */
541
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataTestValidateMasterKey')]
542
-	public function testValidateMasterKey($masterKey): void {
543
-		/** @var KeyManager&MockObject $instance */
544
-		$instance = $this->getMockBuilder(KeyManager::class)
545
-			->setConstructorArgs(
546
-				[
547
-					$this->keyStorageMock,
548
-					$this->cryptMock,
549
-					$this->configMock,
550
-					$this->userMock,
551
-					$this->sessionMock,
552
-					$this->logMock,
553
-					$this->utilMock,
554
-					$this->lockingProviderMock
555
-				]
556
-			)->onlyMethods(['getPublicMasterKey', 'setSystemPrivateKey', 'getMasterKeyPassword'])
557
-			->getMock();
558
-
559
-		$this->utilMock->expects($this->once())->method('isMasterKeyEnabled')
560
-			->willReturn(true);
561
-
562
-		$instance->expects($this->once())->method('getPublicMasterKey')
563
-			->willReturn($masterKey);
564
-
565
-		$instance->expects($this->any())->method('getMasterKeyPassword')->willReturn('masterKeyPassword');
566
-		$this->cryptMock->expects($this->any())->method('generateHeader')->willReturn('header');
567
-
568
-		if (empty($masterKey)) {
569
-			$this->cryptMock->expects($this->once())->method('createKeyPair')
570
-				->willReturn(['publicKey' => 'public', 'privateKey' => 'private']);
571
-			$this->keyStorageMock->expects($this->once())->method('setSystemUserKey')
572
-				->with('systemKeyId.publicKey', 'public', Encryption::ID);
573
-			$this->cryptMock->expects($this->once())->method('encryptPrivateKey')
574
-				->with('private', 'masterKeyPassword', 'systemKeyId')
575
-				->willReturn('EncryptedKey');
576
-			$this->lockingProviderMock->expects($this->once())
577
-				->method('acquireLock');
578
-			$instance->expects($this->once())->method('setSystemPrivateKey')
579
-				->with('systemKeyId', 'headerEncryptedKey');
580
-		} else {
581
-			$this->cryptMock->expects($this->never())->method('createKeyPair');
582
-			$this->keyStorageMock->expects($this->never())->method('setSystemUserKey');
583
-			$this->cryptMock->expects($this->never())->method('encryptPrivateKey');
584
-			$instance->expects($this->never())->method('setSystemPrivateKey');
585
-		}
586
-
587
-		$instance->validateMasterKey();
588
-	}
589
-
590
-	public function testValidateMasterKeyLocked(): void {
591
-		/** @var KeyManager&MockObject $instance */
592
-		$instance = $this->getMockBuilder(KeyManager::class)
593
-			->setConstructorArgs([
594
-				$this->keyStorageMock,
595
-				$this->cryptMock,
596
-				$this->configMock,
597
-				$this->userMock,
598
-				$this->sessionMock,
599
-				$this->logMock,
600
-				$this->utilMock,
601
-				$this->lockingProviderMock
602
-			])
603
-			->onlyMethods(['getPublicMasterKey', 'getPrivateMasterKey', 'setSystemPrivateKey', 'getMasterKeyPassword'])
604
-			->getMock();
605
-
606
-		$this->utilMock->expects($this->once())->method('isMasterKeyEnabled')
607
-			->willReturn(true);
608
-
609
-		$instance->expects($this->once())->method('getPublicMasterKey')
610
-			->willReturn('');
611
-		$instance->expects($this->once())->method('getPrivateMasterKey')
612
-			->willReturn('');
613
-
614
-		$instance->expects($this->any())->method('getMasterKeyPassword')->willReturn('masterKeyPassword');
615
-		$this->cryptMock->expects($this->any())->method('generateHeader')->willReturn('header');
616
-
617
-		$this->lockingProviderMock->expects($this->once())
618
-			->method('acquireLock')
619
-			->willThrowException(new LockedException('encryption-generateMasterKey'));
620
-
621
-		$this->expectException(LockedException::class);
622
-		$instance->validateMasterKey();
623
-	}
624
-
625
-	public static function dataTestValidateMasterKey(): array {
626
-		return [
627
-			['masterKey'],
628
-			['']
629
-		];
630
-	}
631
-
632
-	public function testGetVersionWithoutFileInfo(): void {
633
-		$view = $this->getMockBuilder(View::class)
634
-			->disableOriginalConstructor()->getMock();
635
-		$view->expects($this->once())
636
-			->method('getFileInfo')
637
-			->with('/admin/files/myfile.txt')
638
-			->willReturn(false);
639
-
640
-		/** @var View $view */
641
-		$this->assertSame(0, $this->instance->getVersion('/admin/files/myfile.txt', $view));
642
-	}
643
-
644
-	public function testGetVersionWithFileInfo(): void {
645
-		$view = $this->getMockBuilder(View::class)
646
-			->disableOriginalConstructor()->getMock();
647
-		$fileInfo = $this->getMockBuilder(FileInfo::class)
648
-			->disableOriginalConstructor()->getMock();
649
-		$fileInfo->expects($this->once())
650
-			->method('getEncryptedVersion')
651
-			->willReturn(1337);
652
-		$view->expects($this->once())
653
-			->method('getFileInfo')
654
-			->with('/admin/files/myfile.txt')
655
-			->willReturn($fileInfo);
656
-
657
-		/** @var View $view */
658
-		$this->assertSame(1337, $this->instance->getVersion('/admin/files/myfile.txt', $view));
659
-	}
660
-
661
-	public function testSetVersionWithFileInfo(): void {
662
-		$view = $this->getMockBuilder(View::class)
663
-			->disableOriginalConstructor()->getMock();
664
-		$cache = $this->getMockBuilder(ICache::class)
665
-			->disableOriginalConstructor()->getMock();
666
-		$cache->expects($this->once())
667
-			->method('update')
668
-			->with(123, ['encrypted' => 5, 'encryptedVersion' => 5]);
669
-		$storage = $this->getMockBuilder(FilesIStorage::class)
670
-			->disableOriginalConstructor()->getMock();
671
-		$storage->expects($this->once())
672
-			->method('getCache')
673
-			->willReturn($cache);
674
-		$fileInfo = $this->getMockBuilder(FileInfo::class)
675
-			->disableOriginalConstructor()->getMock();
676
-		$fileInfo->expects($this->once())
677
-			->method('getStorage')
678
-			->willReturn($storage);
679
-		$fileInfo->expects($this->once())
680
-			->method('getId')
681
-			->willReturn(123);
682
-		$view->expects($this->once())
683
-			->method('getFileInfo')
684
-			->with('/admin/files/myfile.txt')
685
-			->willReturn($fileInfo);
686
-
687
-		/** @var View $view */
688
-		$this->instance->setVersion('/admin/files/myfile.txt', 5, $view);
689
-	}
690
-
691
-	public function testSetVersionWithoutFileInfo(): void {
692
-		$view = $this->getMockBuilder(View::class)
693
-			->disableOriginalConstructor()->getMock();
694
-		$view->expects($this->once())
695
-			->method('getFileInfo')
696
-			->with('/admin/files/myfile.txt')
697
-			->willReturn(false);
698
-
699
-		/** @var View $view */
700
-		$this->instance->setVersion('/admin/files/myfile.txt', 5, $view);
701
-	}
702
-
703
-	public function testBackupUserKeys(): void {
704
-		$this->keyStorageMock->expects($this->once())->method('backupUserKeys')
705
-			->with('OC_DEFAULT_MODULE', 'test', 'user1');
706
-		$this->instance->backupUserKeys('test', 'user1');
707
-	}
34
+    protected KeyManager $instance;
35
+
36
+    protected string $userId;
37
+    protected string $systemKeyId;
38
+    protected IStorage&MockObject $keyStorageMock;
39
+    protected Crypt&MockObject $cryptMock;
40
+    protected IUserSession&MockObject $userMock;
41
+    protected Session&MockObject $sessionMock;
42
+    protected LoggerInterface&MockObject $logMock;
43
+    protected Util&MockObject $utilMock;
44
+    protected IConfig&MockObject $configMock;
45
+    protected ILockingProvider&MockObject $lockingProviderMock;
46
+
47
+    protected function setUp(): void {
48
+        parent::setUp();
49
+        $this->userId = 'user1';
50
+        $this->systemKeyId = 'systemKeyId';
51
+        $this->keyStorageMock = $this->createMock(IStorage::class);
52
+        $this->cryptMock = $this->getMockBuilder(Crypt::class)
53
+            ->disableOriginalConstructor()
54
+            ->getMock();
55
+        $this->configMock = $this->createMock(IConfig::class);
56
+        $this->configMock->expects($this->any())
57
+            ->method('getAppValue')
58
+            ->willReturn($this->systemKeyId);
59
+        $this->userMock = $this->createMock(IUserSession::class);
60
+        $this->sessionMock = $this->getMockBuilder(Session::class)
61
+            ->disableOriginalConstructor()
62
+            ->getMock();
63
+        $this->logMock = $this->createMock(LoggerInterface::class);
64
+        $this->utilMock = $this->getMockBuilder(Util::class)
65
+            ->disableOriginalConstructor()
66
+            ->getMock();
67
+        $this->lockingProviderMock = $this->createMock(ILockingProvider::class);
68
+
69
+        $this->instance = new KeyManager(
70
+            $this->keyStorageMock,
71
+            $this->cryptMock,
72
+            $this->configMock,
73
+            $this->userMock,
74
+            $this->sessionMock,
75
+            $this->logMock,
76
+            $this->utilMock,
77
+            $this->lockingProviderMock
78
+        );
79
+    }
80
+
81
+    public function testDeleteShareKey(): void {
82
+        $this->keyStorageMock->expects($this->any())
83
+            ->method('deleteFileKey')
84
+            ->with($this->equalTo('/path'), $this->equalTo('keyId.shareKey'))
85
+            ->willReturn(true);
86
+
87
+        $this->assertTrue(
88
+            $this->instance->deleteShareKey('/path', 'keyId')
89
+        );
90
+    }
91
+
92
+    public function testGetPrivateKey(): void {
93
+        $this->keyStorageMock->expects($this->any())
94
+            ->method('getUserKey')
95
+            ->with($this->equalTo($this->userId), $this->equalTo('privateKey'))
96
+            ->willReturn('privateKey');
97
+
98
+
99
+        $this->assertSame('privateKey',
100
+            $this->instance->getPrivateKey($this->userId)
101
+        );
102
+    }
103
+
104
+    public function testGetPublicKey(): void {
105
+        $this->keyStorageMock->expects($this->any())
106
+            ->method('getUserKey')
107
+            ->with($this->equalTo($this->userId), $this->equalTo('publicKey'))
108
+            ->willReturn('publicKey');
109
+
110
+
111
+        $this->assertSame('publicKey',
112
+            $this->instance->getPublicKey($this->userId)
113
+        );
114
+    }
115
+
116
+    public function testRecoveryKeyExists(): void {
117
+        $this->keyStorageMock->expects($this->any())
118
+            ->method('getSystemUserKey')
119
+            ->with($this->equalTo($this->systemKeyId . '.publicKey'))
120
+            ->willReturn('recoveryKey');
121
+
122
+
123
+        $this->assertTrue($this->instance->recoveryKeyExists());
124
+    }
125
+
126
+    public function testCheckRecoveryKeyPassword(): void {
127
+        $this->keyStorageMock->expects($this->any())
128
+            ->method('getSystemUserKey')
129
+            ->with($this->equalTo($this->systemKeyId . '.privateKey'))
130
+            ->willReturn('recoveryKey');
131
+        $this->cryptMock->expects($this->any())
132
+            ->method('decryptPrivateKey')
133
+            ->with($this->equalTo('recoveryKey'), $this->equalTo('pass'))
134
+            ->willReturn('decryptedRecoveryKey');
135
+
136
+        $this->assertTrue($this->instance->checkRecoveryPassword('pass'));
137
+    }
138
+
139
+    public function testSetPublicKey(): void {
140
+        $this->keyStorageMock->expects($this->any())
141
+            ->method('setUserKey')
142
+            ->with(
143
+                $this->equalTo($this->userId),
144
+                $this->equalTo('publicKey'),
145
+                $this->equalTo('key'))
146
+            ->willReturn(true);
147
+
148
+
149
+        $this->assertTrue(
150
+            $this->instance->setPublicKey($this->userId, 'key')
151
+        );
152
+    }
153
+
154
+    public function testSetPrivateKey(): void {
155
+        $this->keyStorageMock->expects($this->any())
156
+            ->method('setUserKey')
157
+            ->with(
158
+                $this->equalTo($this->userId),
159
+                $this->equalTo('privateKey'),
160
+                $this->equalTo('key'))
161
+            ->willReturn(true);
162
+
163
+
164
+        $this->assertTrue(
165
+            $this->instance->setPrivateKey($this->userId, 'key')
166
+        );
167
+    }
168
+
169
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataTestUserHasKeys')]
170
+    public function testUserHasKeys($key, $expected): void {
171
+        $this->keyStorageMock->expects($this->exactly(2))
172
+            ->method('getUserKey')
173
+            ->with($this->equalTo($this->userId), $this->anything())
174
+            ->willReturn($key);
175
+
176
+
177
+        $this->assertSame($expected,
178
+            $this->instance->userHasKeys($this->userId)
179
+        );
180
+    }
181
+
182
+    public static function dataTestUserHasKeys(): array {
183
+        return [
184
+            ['key', true],
185
+            ['', false]
186
+        ];
187
+    }
188
+
189
+
190
+    public function testUserHasKeysMissingPrivateKey(): void {
191
+        $this->expectException(PrivateKeyMissingException::class);
192
+
193
+        $this->keyStorageMock->expects($this->exactly(2))
194
+            ->method('getUserKey')
195
+            ->willReturnCallback(function ($uid, $keyID, $encryptionModuleId) {
196
+                if ($keyID === 'privateKey') {
197
+                    return '';
198
+                }
199
+                return 'key';
200
+            });
201
+
202
+        $this->instance->userHasKeys($this->userId);
203
+    }
204
+
205
+
206
+    public function testUserHasKeysMissingPublicKey(): void {
207
+        $this->expectException(PublicKeyMissingException::class);
208
+
209
+        $this->keyStorageMock->expects($this->exactly(2))
210
+            ->method('getUserKey')
211
+            ->willReturnCallback(function ($uid, $keyID, $encryptionModuleId) {
212
+                if ($keyID === 'publicKey') {
213
+                    return '';
214
+                }
215
+                return 'key';
216
+            });
217
+
218
+        $this->instance->userHasKeys($this->userId);
219
+    }
220
+
221
+    /**
222
+     * @param bool $useMasterKey
223
+     */
224
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataTestInit')]
225
+    public function testInit($useMasterKey): void {
226
+        /** @var KeyManager&MockObject $instance */
227
+        $instance = $this->getMockBuilder(KeyManager::class)
228
+            ->setConstructorArgs(
229
+                [
230
+                    $this->keyStorageMock,
231
+                    $this->cryptMock,
232
+                    $this->configMock,
233
+                    $this->userMock,
234
+                    $this->sessionMock,
235
+                    $this->logMock,
236
+                    $this->utilMock,
237
+                    $this->lockingProviderMock
238
+                ]
239
+            )->onlyMethods(['getMasterKeyId', 'getMasterKeyPassword', 'getSystemPrivateKey', 'getPrivateKey'])
240
+            ->getMock();
241
+
242
+        $this->utilMock->expects($this->once())->method('isMasterKeyEnabled')
243
+            ->willReturn($useMasterKey);
244
+
245
+        $sessionSetStatusCalls = [];
246
+        $this->sessionMock->expects($this->exactly(2))
247
+            ->method('setStatus')
248
+            ->willReturnCallback(function (string $status) use (&$sessionSetStatusCalls): void {
249
+                $sessionSetStatusCalls[] = $status;
250
+            });
251
+
252
+        $instance->expects($this->any())->method('getMasterKeyId')->willReturn('masterKeyId');
253
+        $instance->expects($this->any())->method('getMasterKeyPassword')->willReturn('masterKeyPassword');
254
+        $instance->expects($this->any())->method('getSystemPrivateKey')->with('masterKeyId')->willReturn('privateMasterKey');
255
+        $instance->expects($this->any())->method('getPrivateKey')->with($this->userId)->willReturn('privateUserKey');
256
+
257
+        if ($useMasterKey) {
258
+            $this->cryptMock->expects($this->once())->method('decryptPrivateKey')
259
+                ->with('privateMasterKey', 'masterKeyPassword', 'masterKeyId')
260
+                ->willReturn('key');
261
+        } else {
262
+            $this->cryptMock->expects($this->once())->method('decryptPrivateKey')
263
+                ->with('privateUserKey', 'pass', $this->userId)
264
+                ->willReturn('key');
265
+        }
266
+
267
+        $this->sessionMock->expects($this->once())->method('setPrivateKey')
268
+            ->with('key');
269
+
270
+        $this->assertTrue($instance->init($this->userId, 'pass'));
271
+        self::assertEquals([
272
+            Session::INIT_EXECUTED,
273
+            Session::INIT_SUCCESSFUL,
274
+        ], $sessionSetStatusCalls);
275
+    }
276
+
277
+    public static function dataTestInit(): array {
278
+        return [
279
+            [true],
280
+            [false]
281
+        ];
282
+    }
283
+
284
+
285
+    public function testSetRecoveryKey(): void {
286
+        $this->keyStorageMock->expects($this->exactly(2))
287
+            ->method('setSystemUserKey')
288
+            ->willReturn(true);
289
+        $this->cryptMock->expects($this->any())
290
+            ->method('encryptPrivateKey')
291
+            ->with($this->equalTo('privateKey'), $this->equalTo('pass'))
292
+            ->willReturn('decryptedPrivateKey');
293
+
294
+
295
+        $this->assertTrue(
296
+            $this->instance->setRecoveryKey('pass',
297
+                ['publicKey' => 'publicKey', 'privateKey' => 'privateKey'])
298
+        );
299
+    }
300
+
301
+    public function testSetSystemPrivateKey(): void {
302
+        $this->keyStorageMock->expects($this->exactly(1))
303
+            ->method('setSystemUserKey')
304
+            ->with($this->equalTo('keyId.privateKey'), $this->equalTo('key'))
305
+            ->willReturn(true);
306
+
307
+
308
+        $this->assertTrue(
309
+            $this->instance->setSystemPrivateKey('keyId', 'key')
310
+        );
311
+    }
312
+
313
+    public function testGetSystemPrivateKey(): void {
314
+        $this->keyStorageMock->expects($this->exactly(1))
315
+            ->method('getSystemUserKey')
316
+            ->with($this->equalTo('keyId.privateKey'))
317
+            ->willReturn('systemPrivateKey');
318
+
319
+
320
+        $this->assertSame('systemPrivateKey',
321
+            $this->instance->getSystemPrivateKey('keyId')
322
+        );
323
+    }
324
+
325
+    public function testGetEncryptedFileKey(): void {
326
+        $this->keyStorageMock->expects($this->once())
327
+            ->method('getFileKey')
328
+            ->with('/', 'fileKey')
329
+            ->willReturn(true);
330
+
331
+        $this->assertTrue($this->instance->getEncryptedFileKey('/'));
332
+    }
333
+
334
+    public static function dataTestGetFileKey(): array {
335
+        return [
336
+            ['user1', false, 'privateKey', 'legacyKey', 'multiKeyDecryptResult'],
337
+            ['user1', false, 'privateKey', '', 'multiKeyDecryptResult'],
338
+            ['user1', false, false, 'legacyKey', ''],
339
+            ['user1', false, false, '', ''],
340
+            ['user1', true, 'privateKey', 'legacyKey', 'multiKeyDecryptResult'],
341
+            ['user1', true, 'privateKey', '', 'multiKeyDecryptResult'],
342
+            ['user1', true, false, 'legacyKey', ''],
343
+            ['user1', true, false, '', ''],
344
+            [null, false, 'privateKey', 'legacyKey', 'multiKeyDecryptResult'],
345
+            [null, false, 'privateKey', '', 'multiKeyDecryptResult'],
346
+            [null, false, false, 'legacyKey', ''],
347
+            [null, false, false, '', ''],
348
+            [null, true, 'privateKey', 'legacyKey', 'multiKeyDecryptResult'],
349
+            [null, true, 'privateKey', '', 'multiKeyDecryptResult'],
350
+            [null, true, false, 'legacyKey', ''],
351
+            [null, true, false, '', ''],
352
+        ];
353
+    }
354
+
355
+    /**
356
+     *
357
+     * @param $uid
358
+     * @param $isMasterKeyEnabled
359
+     * @param $privateKey
360
+     * @param $expected
361
+     */
362
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataTestGetFileKey')]
363
+    public function testGetFileKey($uid, $isMasterKeyEnabled, $privateKey, $encryptedFileKey, $expected): void {
364
+        $path = '/foo.txt';
365
+
366
+        if ($isMasterKeyEnabled) {
367
+            $expectedUid = 'masterKeyId';
368
+            $this->configMock->expects($this->any())->method('getSystemValue')->with('secret')
369
+                ->willReturn('password');
370
+        } elseif (!$uid) {
371
+            $expectedUid = 'systemKeyId';
372
+        } else {
373
+            $expectedUid = $uid;
374
+        }
375
+
376
+        $this->invokePrivate($this->instance, 'masterKeyId', ['masterKeyId']);
377
+
378
+        $this->keyStorageMock->expects($this->exactly(2))
379
+            ->method('getFileKey')
380
+            ->willReturnMap([
381
+                [$path, 'fileKey', 'OC_DEFAULT_MODULE', $encryptedFileKey],
382
+                [$path, $expectedUid . '.shareKey', 'OC_DEFAULT_MODULE', 'fileKey'],
383
+            ]);
384
+
385
+        $this->utilMock->expects($this->any())->method('isMasterKeyEnabled')
386
+            ->willReturn($isMasterKeyEnabled);
387
+
388
+        if (is_null($uid)) {
389
+            $this->keyStorageMock->expects($this->once())
390
+                ->method('getSystemUserKey')
391
+                ->willReturn(true);
392
+            $this->cryptMock->expects($this->once())
393
+                ->method('decryptPrivateKey')
394
+                ->willReturn($privateKey);
395
+        } else {
396
+            $this->keyStorageMock->expects($this->never())
397
+                ->method('getSystemUserKey');
398
+            $this->sessionMock->expects($this->once())->method('getPrivateKey')->willReturn($privateKey);
399
+        }
400
+
401
+        if (!empty($encryptedFileKey)) {
402
+            $this->cryptMock->expects($this->never())
403
+                ->method('multiKeyDecrypt');
404
+            if ($privateKey) {
405
+                $this->cryptMock->expects($this->once())
406
+                    ->method('multiKeyDecryptLegacy')
407
+                    ->willReturn('multiKeyDecryptResult');
408
+            } else {
409
+                $this->cryptMock->expects($this->never())
410
+                    ->method('multiKeyDecryptLegacy');
411
+            }
412
+        } else {
413
+            $this->cryptMock->expects($this->never())
414
+                ->method('multiKeyDecryptLegacy');
415
+            if ($privateKey) {
416
+                $this->cryptMock->expects($this->once())
417
+                    ->method('multiKeyDecrypt')
418
+                    ->willReturn('multiKeyDecryptResult');
419
+            } else {
420
+                $this->cryptMock->expects($this->never())
421
+                    ->method('multiKeyDecrypt');
422
+            }
423
+        }
424
+
425
+        $this->assertSame($expected,
426
+            $this->instance->getFileKey($path, $uid, null)
427
+        );
428
+    }
429
+
430
+    public function testDeletePrivateKey(): void {
431
+        $this->keyStorageMock->expects($this->once())
432
+            ->method('deleteUserKey')
433
+            ->with('user1', 'privateKey')
434
+            ->willReturn(true);
435
+
436
+        $this->assertTrue(self::invokePrivate($this->instance,
437
+            'deletePrivateKey',
438
+            [$this->userId]));
439
+    }
440
+
441
+    public function testDeleteAllFileKeys(): void {
442
+        $this->keyStorageMock->expects($this->once())
443
+            ->method('deleteAllFileKeys')
444
+            ->willReturn(true);
445
+
446
+        $this->assertTrue($this->instance->deleteAllFileKeys('/'));
447
+    }
448
+
449
+    /**
450
+     * test add public share key and or recovery key to the list of public keys
451
+     *
452
+     *
453
+     * @param array $accessList
454
+     * @param array $publicKeys
455
+     * @param string $uid
456
+     * @param array $expectedKeys
457
+     */
458
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataTestAddSystemKeys')]
459
+    public function testAddSystemKeys($accessList, $publicKeys, $uid, $expectedKeys): void {
460
+        $publicShareKeyId = 'publicShareKey';
461
+        $recoveryKeyId = 'recoveryKey';
462
+
463
+        $this->keyStorageMock->expects($this->any())
464
+            ->method('getSystemUserKey')
465
+            ->willReturnCallback(function ($keyId, $encryptionModuleId) {
466
+                return $keyId;
467
+            });
468
+
469
+        $this->utilMock->expects($this->any())
470
+            ->method('isRecoveryEnabledForUser')
471
+            ->willReturnCallback(function ($uid) {
472
+                if ($uid === 'user1') {
473
+                    return true;
474
+                }
475
+                return false;
476
+            });
477
+
478
+        // set key IDs
479
+        self::invokePrivate($this->instance, 'publicShareKeyId', [$publicShareKeyId]);
480
+        self::invokePrivate($this->instance, 'recoveryKeyId', [$recoveryKeyId]);
481
+
482
+        $result = $this->instance->addSystemKeys($accessList, $publicKeys, $uid);
483
+
484
+        foreach ($expectedKeys as $expected) {
485
+            $this->assertArrayHasKey($expected, $result);
486
+        }
487
+
488
+        $this->assertSameSize($expectedKeys, $result);
489
+    }
490
+
491
+    /**
492
+     * data provider for testAddSystemKeys()
493
+     *
494
+     * @return array
495
+     */
496
+    public static function dataTestAddSystemKeys(): array {
497
+        return [
498
+            [['public' => true],[], 'user1', ['publicShareKey', 'recoveryKey']],
499
+            [['public' => false], [], 'user1', ['recoveryKey']],
500
+            [['public' => true],[], 'user2', ['publicShareKey']],
501
+            [['public' => false], [], 'user2', []],
502
+        ];
503
+    }
504
+
505
+    public function testGetMasterKeyId(): void {
506
+        $this->assertSame('systemKeyId', $this->instance->getMasterKeyId());
507
+    }
508
+
509
+    public function testGetPublicMasterKey(): void {
510
+        $this->keyStorageMock->expects($this->once())->method('getSystemUserKey')
511
+            ->with('systemKeyId.publicKey', Encryption::ID)
512
+            ->willReturn(true);
513
+
514
+        $this->assertTrue(
515
+            $this->instance->getPublicMasterKey()
516
+        );
517
+    }
518
+
519
+    public function testGetMasterKeyPassword(): void {
520
+        $this->configMock->expects($this->once())->method('getSystemValue')->with('secret')
521
+            ->willReturn('password');
522
+
523
+        $this->assertSame('password',
524
+            $this->invokePrivate($this->instance, 'getMasterKeyPassword', [])
525
+        );
526
+    }
527
+
528
+
529
+    public function testGetMasterKeyPasswordException(): void {
530
+        $this->expectException(\Exception::class);
531
+
532
+        $this->configMock->expects($this->once())->method('getSystemValue')->with('secret')
533
+            ->willReturn('');
534
+
535
+        $this->invokePrivate($this->instance, 'getMasterKeyPassword', []);
536
+    }
537
+
538
+    /**
539
+     * @param $masterKey
540
+     */
541
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataTestValidateMasterKey')]
542
+    public function testValidateMasterKey($masterKey): void {
543
+        /** @var KeyManager&MockObject $instance */
544
+        $instance = $this->getMockBuilder(KeyManager::class)
545
+            ->setConstructorArgs(
546
+                [
547
+                    $this->keyStorageMock,
548
+                    $this->cryptMock,
549
+                    $this->configMock,
550
+                    $this->userMock,
551
+                    $this->sessionMock,
552
+                    $this->logMock,
553
+                    $this->utilMock,
554
+                    $this->lockingProviderMock
555
+                ]
556
+            )->onlyMethods(['getPublicMasterKey', 'setSystemPrivateKey', 'getMasterKeyPassword'])
557
+            ->getMock();
558
+
559
+        $this->utilMock->expects($this->once())->method('isMasterKeyEnabled')
560
+            ->willReturn(true);
561
+
562
+        $instance->expects($this->once())->method('getPublicMasterKey')
563
+            ->willReturn($masterKey);
564
+
565
+        $instance->expects($this->any())->method('getMasterKeyPassword')->willReturn('masterKeyPassword');
566
+        $this->cryptMock->expects($this->any())->method('generateHeader')->willReturn('header');
567
+
568
+        if (empty($masterKey)) {
569
+            $this->cryptMock->expects($this->once())->method('createKeyPair')
570
+                ->willReturn(['publicKey' => 'public', 'privateKey' => 'private']);
571
+            $this->keyStorageMock->expects($this->once())->method('setSystemUserKey')
572
+                ->with('systemKeyId.publicKey', 'public', Encryption::ID);
573
+            $this->cryptMock->expects($this->once())->method('encryptPrivateKey')
574
+                ->with('private', 'masterKeyPassword', 'systemKeyId')
575
+                ->willReturn('EncryptedKey');
576
+            $this->lockingProviderMock->expects($this->once())
577
+                ->method('acquireLock');
578
+            $instance->expects($this->once())->method('setSystemPrivateKey')
579
+                ->with('systemKeyId', 'headerEncryptedKey');
580
+        } else {
581
+            $this->cryptMock->expects($this->never())->method('createKeyPair');
582
+            $this->keyStorageMock->expects($this->never())->method('setSystemUserKey');
583
+            $this->cryptMock->expects($this->never())->method('encryptPrivateKey');
584
+            $instance->expects($this->never())->method('setSystemPrivateKey');
585
+        }
586
+
587
+        $instance->validateMasterKey();
588
+    }
589
+
590
+    public function testValidateMasterKeyLocked(): void {
591
+        /** @var KeyManager&MockObject $instance */
592
+        $instance = $this->getMockBuilder(KeyManager::class)
593
+            ->setConstructorArgs([
594
+                $this->keyStorageMock,
595
+                $this->cryptMock,
596
+                $this->configMock,
597
+                $this->userMock,
598
+                $this->sessionMock,
599
+                $this->logMock,
600
+                $this->utilMock,
601
+                $this->lockingProviderMock
602
+            ])
603
+            ->onlyMethods(['getPublicMasterKey', 'getPrivateMasterKey', 'setSystemPrivateKey', 'getMasterKeyPassword'])
604
+            ->getMock();
605
+
606
+        $this->utilMock->expects($this->once())->method('isMasterKeyEnabled')
607
+            ->willReturn(true);
608
+
609
+        $instance->expects($this->once())->method('getPublicMasterKey')
610
+            ->willReturn('');
611
+        $instance->expects($this->once())->method('getPrivateMasterKey')
612
+            ->willReturn('');
613
+
614
+        $instance->expects($this->any())->method('getMasterKeyPassword')->willReturn('masterKeyPassword');
615
+        $this->cryptMock->expects($this->any())->method('generateHeader')->willReturn('header');
616
+
617
+        $this->lockingProviderMock->expects($this->once())
618
+            ->method('acquireLock')
619
+            ->willThrowException(new LockedException('encryption-generateMasterKey'));
620
+
621
+        $this->expectException(LockedException::class);
622
+        $instance->validateMasterKey();
623
+    }
624
+
625
+    public static function dataTestValidateMasterKey(): array {
626
+        return [
627
+            ['masterKey'],
628
+            ['']
629
+        ];
630
+    }
631
+
632
+    public function testGetVersionWithoutFileInfo(): void {
633
+        $view = $this->getMockBuilder(View::class)
634
+            ->disableOriginalConstructor()->getMock();
635
+        $view->expects($this->once())
636
+            ->method('getFileInfo')
637
+            ->with('/admin/files/myfile.txt')
638
+            ->willReturn(false);
639
+
640
+        /** @var View $view */
641
+        $this->assertSame(0, $this->instance->getVersion('/admin/files/myfile.txt', $view));
642
+    }
643
+
644
+    public function testGetVersionWithFileInfo(): void {
645
+        $view = $this->getMockBuilder(View::class)
646
+            ->disableOriginalConstructor()->getMock();
647
+        $fileInfo = $this->getMockBuilder(FileInfo::class)
648
+            ->disableOriginalConstructor()->getMock();
649
+        $fileInfo->expects($this->once())
650
+            ->method('getEncryptedVersion')
651
+            ->willReturn(1337);
652
+        $view->expects($this->once())
653
+            ->method('getFileInfo')
654
+            ->with('/admin/files/myfile.txt')
655
+            ->willReturn($fileInfo);
656
+
657
+        /** @var View $view */
658
+        $this->assertSame(1337, $this->instance->getVersion('/admin/files/myfile.txt', $view));
659
+    }
660
+
661
+    public function testSetVersionWithFileInfo(): void {
662
+        $view = $this->getMockBuilder(View::class)
663
+            ->disableOriginalConstructor()->getMock();
664
+        $cache = $this->getMockBuilder(ICache::class)
665
+            ->disableOriginalConstructor()->getMock();
666
+        $cache->expects($this->once())
667
+            ->method('update')
668
+            ->with(123, ['encrypted' => 5, 'encryptedVersion' => 5]);
669
+        $storage = $this->getMockBuilder(FilesIStorage::class)
670
+            ->disableOriginalConstructor()->getMock();
671
+        $storage->expects($this->once())
672
+            ->method('getCache')
673
+            ->willReturn($cache);
674
+        $fileInfo = $this->getMockBuilder(FileInfo::class)
675
+            ->disableOriginalConstructor()->getMock();
676
+        $fileInfo->expects($this->once())
677
+            ->method('getStorage')
678
+            ->willReturn($storage);
679
+        $fileInfo->expects($this->once())
680
+            ->method('getId')
681
+            ->willReturn(123);
682
+        $view->expects($this->once())
683
+            ->method('getFileInfo')
684
+            ->with('/admin/files/myfile.txt')
685
+            ->willReturn($fileInfo);
686
+
687
+        /** @var View $view */
688
+        $this->instance->setVersion('/admin/files/myfile.txt', 5, $view);
689
+    }
690
+
691
+    public function testSetVersionWithoutFileInfo(): void {
692
+        $view = $this->getMockBuilder(View::class)
693
+            ->disableOriginalConstructor()->getMock();
694
+        $view->expects($this->once())
695
+            ->method('getFileInfo')
696
+            ->with('/admin/files/myfile.txt')
697
+            ->willReturn(false);
698
+
699
+        /** @var View $view */
700
+        $this->instance->setVersion('/admin/files/myfile.txt', 5, $view);
701
+    }
702
+
703
+    public function testBackupUserKeys(): void {
704
+        $this->keyStorageMock->expects($this->once())->method('backupUserKeys')
705
+            ->with('OC_DEFAULT_MODULE', 'test', 'user1');
706
+        $this->instance->backupUserKeys('test', 'user1');
707
+    }
708 708
 }
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -116,7 +116,7 @@  discard block
 block discarded – undo
116 116
 	public function testRecoveryKeyExists(): void {
117 117
 		$this->keyStorageMock->expects($this->any())
118 118
 			->method('getSystemUserKey')
119
-			->with($this->equalTo($this->systemKeyId . '.publicKey'))
119
+			->with($this->equalTo($this->systemKeyId.'.publicKey'))
120 120
 			->willReturn('recoveryKey');
121 121
 
122 122
 
@@ -126,7 +126,7 @@  discard block
 block discarded – undo
126 126
 	public function testCheckRecoveryKeyPassword(): void {
127 127
 		$this->keyStorageMock->expects($this->any())
128 128
 			->method('getSystemUserKey')
129
-			->with($this->equalTo($this->systemKeyId . '.privateKey'))
129
+			->with($this->equalTo($this->systemKeyId.'.privateKey'))
130 130
 			->willReturn('recoveryKey');
131 131
 		$this->cryptMock->expects($this->any())
132 132
 			->method('decryptPrivateKey')
@@ -192,7 +192,7 @@  discard block
 block discarded – undo
192 192
 
193 193
 		$this->keyStorageMock->expects($this->exactly(2))
194 194
 			->method('getUserKey')
195
-			->willReturnCallback(function ($uid, $keyID, $encryptionModuleId) {
195
+			->willReturnCallback(function($uid, $keyID, $encryptionModuleId) {
196 196
 				if ($keyID === 'privateKey') {
197 197
 					return '';
198 198
 				}
@@ -208,7 +208,7 @@  discard block
 block discarded – undo
208 208
 
209 209
 		$this->keyStorageMock->expects($this->exactly(2))
210 210
 			->method('getUserKey')
211
-			->willReturnCallback(function ($uid, $keyID, $encryptionModuleId) {
211
+			->willReturnCallback(function($uid, $keyID, $encryptionModuleId) {
212 212
 				if ($keyID === 'publicKey') {
213 213
 					return '';
214 214
 				}
@@ -245,7 +245,7 @@  discard block
 block discarded – undo
245 245
 		$sessionSetStatusCalls = [];
246 246
 		$this->sessionMock->expects($this->exactly(2))
247 247
 			->method('setStatus')
248
-			->willReturnCallback(function (string $status) use (&$sessionSetStatusCalls): void {
248
+			->willReturnCallback(function(string $status) use (&$sessionSetStatusCalls): void {
249 249
 				$sessionSetStatusCalls[] = $status;
250 250
 			});
251 251
 
@@ -379,7 +379,7 @@  discard block
 block discarded – undo
379 379
 			->method('getFileKey')
380 380
 			->willReturnMap([
381 381
 				[$path, 'fileKey', 'OC_DEFAULT_MODULE', $encryptedFileKey],
382
-				[$path, $expectedUid . '.shareKey', 'OC_DEFAULT_MODULE', 'fileKey'],
382
+				[$path, $expectedUid.'.shareKey', 'OC_DEFAULT_MODULE', 'fileKey'],
383 383
 			]);
384 384
 
385 385
 		$this->utilMock->expects($this->any())->method('isMasterKeyEnabled')
@@ -462,13 +462,13 @@  discard block
 block discarded – undo
462 462
 
463 463
 		$this->keyStorageMock->expects($this->any())
464 464
 			->method('getSystemUserKey')
465
-			->willReturnCallback(function ($keyId, $encryptionModuleId) {
465
+			->willReturnCallback(function($keyId, $encryptionModuleId) {
466 466
 				return $keyId;
467 467
 			});
468 468
 
469 469
 		$this->utilMock->expects($this->any())
470 470
 			->method('isRecoveryEnabledForUser')
471
-			->willReturnCallback(function ($uid) {
471
+			->willReturnCallback(function($uid) {
472 472
 				if ($uid === 'user1') {
473 473
 					return true;
474 474
 				}
@@ -495,9 +495,9 @@  discard block
 block discarded – undo
495 495
 	 */
496 496
 	public static function dataTestAddSystemKeys(): array {
497 497
 		return [
498
-			[['public' => true],[], 'user1', ['publicShareKey', 'recoveryKey']],
498
+			[['public' => true], [], 'user1', ['publicShareKey', 'recoveryKey']],
499 499
 			[['public' => false], [], 'user1', ['recoveryKey']],
500
-			[['public' => true],[], 'user2', ['publicShareKey']],
500
+			[['public' => true], [], 'user2', ['publicShareKey']],
501 501
 			[['public' => false], [], 'user2', []],
502 502
 		];
503 503
 	}
Please login to merge, or discard this patch.
apps/user_status/tests/Unit/Db/UserStatusMapperTest.php 1 patch
Indentation   +314 added lines, -314 removed lines patch added patch discarded remove patch
@@ -15,318 +15,318 @@
 block discarded – undo
15 15
 use Test\TestCase;
16 16
 
17 17
 class UserStatusMapperTest extends TestCase {
18
-	private UserStatusMapper $mapper;
19
-
20
-	protected function setUp(): void {
21
-		parent::setUp();
22
-
23
-		// make sure that DB is empty
24
-		$qb = self::$realDatabase->getQueryBuilder();
25
-		$qb->delete('user_status')->execute();
26
-
27
-		$this->mapper = new UserStatusMapper(self::$realDatabase);
28
-	}
29
-
30
-	public function testGetTableName(): void {
31
-		$this->assertEquals('user_status', $this->mapper->getTableName());
32
-	}
33
-
34
-	public function testGetFindAll(): void {
35
-		$this->insertSampleStatuses();
36
-
37
-		$allResults = $this->mapper->findAll();
38
-		$this->assertCount(3, $allResults);
39
-
40
-		$limitedResults = $this->mapper->findAll(2);
41
-		$this->assertCount(2, $limitedResults);
42
-		$this->assertEquals('admin', $limitedResults[0]->getUserId());
43
-		$this->assertEquals('user1', $limitedResults[1]->getUserId());
44
-
45
-		$offsetResults = $this->mapper->findAll(null, 2);
46
-		$this->assertCount(1, $offsetResults);
47
-		$this->assertEquals('user2', $offsetResults[0]->getUserId());
48
-	}
49
-
50
-	public function testFindAllRecent(): void {
51
-		$this->insertSampleStatuses();
52
-
53
-		$allResults = $this->mapper->findAllRecent(2, 0);
54
-		$this->assertCount(2, $allResults);
55
-		$this->assertEquals('user2', $allResults[0]->getUserId());
56
-		$this->assertEquals('user1', $allResults[1]->getUserId());
57
-	}
58
-
59
-	public function testGetFind(): void {
60
-		$this->insertSampleStatuses();
61
-
62
-		$adminStatus = $this->mapper->findByUserId('admin');
63
-		$this->assertEquals('admin', $adminStatus->getUserId());
64
-		$this->assertEquals('offline', $adminStatus->getStatus());
65
-		$this->assertEquals(0, $adminStatus->getStatusTimestamp());
66
-		$this->assertEquals(false, $adminStatus->getIsUserDefined());
67
-		$this->assertEquals(null, $adminStatus->getCustomIcon());
68
-		$this->assertEquals(null, $adminStatus->getCustomMessage());
69
-		$this->assertEquals(null, $adminStatus->getClearAt());
70
-
71
-		$user1Status = $this->mapper->findByUserId('user1');
72
-		$this->assertEquals('user1', $user1Status->getUserId());
73
-		$this->assertEquals('dnd', $user1Status->getStatus());
74
-		$this->assertEquals(5000, $user1Status->getStatusTimestamp());
75
-		$this->assertEquals(true, $user1Status->getIsUserDefined());
76
-		$this->assertEquals('
Please login to merge, or discard this patch.
apps/user_status/tests/Unit/Controller/UserStatusControllerTest.php 1 patch
Indentation   +283 added lines, -283 removed lines patch added patch discarded remove patch
@@ -27,287 +27,287 @@
 block discarded – undo
27 27
 use Throwable;
28 28
 
29 29
 class UserStatusControllerTest extends TestCase {
30
-	private LoggerInterface&MockObject $logger;
31
-	private StatusService&MockObject $statusService;
32
-	private CalendarStatusService&MockObject $calendarStatusService;
33
-	private UserStatusController $controller;
34
-
35
-	protected function setUp(): void {
36
-		parent::setUp();
37
-
38
-		$request = $this->createMock(IRequest::class);
39
-		$userId = 'john.doe';
40
-		$this->logger = $this->createMock(LoggerInterface::class);
41
-		$this->statusService = $this->createMock(StatusService::class);
42
-		$this->calendarStatusService = $this->createMock(CalendarStatusService::class);
43
-
44
-		$this->controller = new UserStatusController(
45
-			'user_status',
46
-			$request,
47
-			$userId,
48
-			$this->logger,
49
-			$this->statusService,
50
-			$this->calendarStatusService,
51
-		);
52
-	}
53
-
54
-	public function testGetStatus(): void {
55
-		$userStatus = $this->getUserStatus();
56
-
57
-		$this->statusService->expects($this->once())
58
-			->method('findByUserId')
59
-			->with('john.doe')
60
-			->willReturn($userStatus);
61
-
62
-		$response = $this->controller->getStatus();
63
-		$this->assertEquals([
64
-			'userId' => 'john.doe',
65
-			'status' => 'invisible',
66
-			'icon' => '
Please login to merge, or discard this patch.
apps/user_status/tests/Unit/Service/StatusServiceTest.php 2 patches
Indentation   +794 added lines, -794 removed lines patch added patch discarded remove patch
@@ -31,798 +31,798 @@
 block discarded – undo
31 31
 use Test\TestCase;
32 32
 
33 33
 class StatusServiceTest extends TestCase {
34
-	private UserStatusMapper&MockObject $mapper;
35
-	private ITimeFactory&MockObject $timeFactory;
36
-	private PredefinedStatusService&MockObject $predefinedStatusService;
37
-	private IEmojiHelper&MockObject $emojiHelper;
38
-	private IConfig&MockObject $config;
39
-	private IUserManager&MockObject $userManager;
40
-	private LoggerInterface&MockObject $logger;
41
-
42
-	private StatusService $service;
43
-
44
-	protected function setUp(): void {
45
-		parent::setUp();
46
-
47
-		$this->mapper = $this->createMock(UserStatusMapper::class);
48
-		$this->timeFactory = $this->createMock(ITimeFactory::class);
49
-		$this->predefinedStatusService = $this->createMock(PredefinedStatusService::class);
50
-		$this->emojiHelper = $this->createMock(IEmojiHelper::class);
51
-		$this->userManager = $this->createMock(IUserManager::class);
52
-		$this->config = $this->createMock(IConfig::class);
53
-		$this->logger = $this->createMock(LoggerInterface::class);
54
-
55
-		$this->config->method('getAppValue')
56
-			->willReturnMap([
57
-				['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'],
58
-				['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'no']
59
-			]);
60
-
61
-		$this->service = new StatusService($this->mapper,
62
-			$this->timeFactory,
63
-			$this->predefinedStatusService,
64
-			$this->emojiHelper,
65
-			$this->config,
66
-			$this->userManager,
67
-			$this->logger,
68
-		);
69
-	}
70
-
71
-	public function testFindAll(): void {
72
-		$status1 = $this->createMock(UserStatus::class);
73
-		$status2 = $this->createMock(UserStatus::class);
74
-
75
-		$this->mapper->expects($this->once())
76
-			->method('findAll')
77
-			->with(20, 50)
78
-			->willReturn([$status1, $status2]);
79
-
80
-		$this->assertEquals([
81
-			$status1,
82
-			$status2,
83
-		], $this->service->findAll(20, 50));
84
-	}
85
-
86
-	public function testFindAllRecentStatusChanges(): void {
87
-		$status1 = $this->createMock(UserStatus::class);
88
-		$status2 = $this->createMock(UserStatus::class);
89
-
90
-		$this->mapper->expects($this->once())
91
-			->method('findAllRecent')
92
-			->with(20, 50)
93
-			->willReturn([$status1, $status2]);
94
-
95
-		$this->assertEquals([
96
-			$status1,
97
-			$status2,
98
-		], $this->service->findAllRecentStatusChanges(20, 50));
99
-	}
100
-
101
-	public function testFindAllRecentStatusChangesNoEnumeration(): void {
102
-		$status1 = $this->createMock(UserStatus::class);
103
-		$status2 = $this->createMock(UserStatus::class);
104
-
105
-		$this->mapper->method('findAllRecent')
106
-			->with(20, 50)
107
-			->willReturn([$status1, $status2]);
108
-
109
-		// Rebuild $this->service with user enumeration turned off
110
-		$this->config = $this->createMock(IConfig::class);
111
-
112
-		$this->config->method('getAppValue')
113
-			->willReturnMap([
114
-				['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'no'],
115
-				['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'no']
116
-			]);
117
-
118
-		$this->service = new StatusService($this->mapper,
119
-			$this->timeFactory,
120
-			$this->predefinedStatusService,
121
-			$this->emojiHelper,
122
-			$this->config,
123
-			$this->userManager,
124
-			$this->logger,
125
-		);
126
-
127
-		$this->assertEquals([], $this->service->findAllRecentStatusChanges(20, 50));
128
-
129
-		// Rebuild $this->service with user enumeration limited to common groups
130
-		$this->config = $this->createMock(IConfig::class);
131
-
132
-		$this->config->method('getAppValue')
133
-			->willReturnMap([
134
-				['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'],
135
-				['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'yes']
136
-			]);
137
-
138
-		$this->service = new StatusService($this->mapper,
139
-			$this->timeFactory,
140
-			$this->predefinedStatusService,
141
-			$this->emojiHelper,
142
-			$this->config,
143
-			$this->userManager,
144
-			$this->logger,
145
-		);
146
-
147
-		$this->assertEquals([], $this->service->findAllRecentStatusChanges(20, 50));
148
-	}
149
-
150
-	public function testFindByUserIdDoesNotExist(): void {
151
-		$this->mapper->expects($this->once())
152
-			->method('findByUserId')
153
-			->with('john.doe')
154
-			->willThrowException(new DoesNotExistException(''));
155
-
156
-		$this->expectException(DoesNotExistException::class);
157
-		$this->service->findByUserId('john.doe');
158
-	}
159
-
160
-	public function testFindAllAddDefaultMessage(): void {
161
-		$status = new UserStatus();
162
-		$status->setMessageId('commuting');
163
-
164
-		$this->predefinedStatusService->expects($this->once())
165
-			->method('getDefaultStatusById')
166
-			->with('commuting')
167
-			->willReturn([
168
-				'id' => 'commuting',
169
-				'icon' => '
Please login to merge, or discard this patch.
Spacing   +65 added lines, -65 removed lines patch added patch discarded remove patch
@@ -286,59 +286,59 @@  discard block
 block discarded – undo
286 286
 
287 287
 	public static function setStatusDataProvider(): array {
288 288
 		return [
289
-			['john.doe', 'online', 50,   true,  true,  true, false, false, null, null],
290
-			['john.doe', 'online', 50,   true,  false, true, false, false, null, null],
291
-			['john.doe', 'online', 50,   false, true,  true, false, false, null, null],
292
-			['john.doe', 'online', 50,   false, false, true, false, false, null, null],
293
-			['john.doe', 'online', null, true,  true,  true, true,  false, null, null],
294
-			['john.doe', 'online', null, true,  false, true, true,  false, null, null],
295
-			['john.doe', 'online', null, false, true,  true, true,  false, null, null],
296
-			['john.doe', 'online', null, false, false, true, true,  false, null, null],
297
-
298
-			['john.doe', 'away', 50,   true,  true,  true, false, false, null, null],
299
-			['john.doe', 'away', 50,   true,  false, true, false, false, null, null],
300
-			['john.doe', 'away', 50,   false, true,  true, false, false, null, null],
301
-			['john.doe', 'away', 50,   false, false, true, false, false, null, null],
302
-			['john.doe', 'away', null, true,  true,  true, true,  false, null, null],
303
-			['john.doe', 'away', null, true,  false, true, true,  false, null, null],
304
-			['john.doe', 'away', null, false, true,  true, true,  false, null, null],
305
-			['john.doe', 'away', null, false, false, true, true,  false, null, null],
306
-
307
-			['john.doe', 'dnd', 50,   true,  true,  true, false, false, null, null],
308
-			['john.doe', 'dnd', 50,   true,  false, true, false, false, null, null],
309
-			['john.doe', 'dnd', 50,   false, true,  true, false, false, null, null],
310
-			['john.doe', 'dnd', 50,   false, false, true, false, false, null, null],
311
-			['john.doe', 'dnd', null, true,  true,  true, true,  false, null, null],
312
-			['john.doe', 'dnd', null, true,  false, true, true,  false, null, null],
313
-			['john.doe', 'dnd', null, false, true,  true, true,  false, null, null],
314
-			['john.doe', 'dnd', null, false, false, true, true,  false, null, null],
315
-
316
-			['john.doe', 'invisible', 50,   true,  true,  true, false, false, null, null],
317
-			['john.doe', 'invisible', 50,   true,  false, true, false, false, null, null],
318
-			['john.doe', 'invisible', 50,   false, true,  true, false, false, null, null],
319
-			['john.doe', 'invisible', 50,   false, false, true, false, false, null, null],
320
-			['john.doe', 'invisible', null, true,  true,  true, true,  false, null, null],
321
-			['john.doe', 'invisible', null, true,  false, true, true,  false, null, null],
322
-			['john.doe', 'invisible', null, false, true,  true, true,  false, null, null],
323
-			['john.doe', 'invisible', null, false, false, true, true,  false, null, null],
324
-
325
-			['john.doe', 'offline', 50,   true,  true,  true, false, false, null, null],
326
-			['john.doe', 'offline', 50,   true,  false, true, false, false, null, null],
327
-			['john.doe', 'offline', 50,   false, true,  true, false, false, null, null],
328
-			['john.doe', 'offline', 50,   false, false, true, false, false, null, null],
329
-			['john.doe', 'offline', null, true,  true,  true, true,  false, null, null],
330
-			['john.doe', 'offline', null, true,  false, true, true,  false, null, null],
331
-			['john.doe', 'offline', null, false, true,  true, true,  false, null, null],
332
-			['john.doe', 'offline', null, false, false, true, true,  false, null, null],
333
-
334
-			['john.doe', 'illegal-status', 50,   true,  true,  false, false, true, InvalidStatusTypeException::class, 'Status-type "illegal-status" is not supported'],
335
-			['john.doe', 'illegal-status', 50,   true,  false, false, false, true, InvalidStatusTypeException::class, 'Status-type "illegal-status" is not supported'],
336
-			['john.doe', 'illegal-status', 50,   false, true,  false, false, true, InvalidStatusTypeException::class, 'Status-type "illegal-status" is not supported'],
337
-			['john.doe', 'illegal-status', 50,   false, false, false, false, true, InvalidStatusTypeException::class, 'Status-type "illegal-status" is not supported'],
338
-			['john.doe', 'illegal-status', null, true,  true,  false, true,  true, InvalidStatusTypeException::class, 'Status-type "illegal-status" is not supported'],
339
-			['john.doe', 'illegal-status', null, true,  false, false, true,  true, InvalidStatusTypeException::class, 'Status-type "illegal-status" is not supported'],
340
-			['john.doe', 'illegal-status', null, false, true,  false, true,  true, InvalidStatusTypeException::class, 'Status-type "illegal-status" is not supported'],
341
-			['john.doe', 'illegal-status', null, false, false, false, true,  true, InvalidStatusTypeException::class, 'Status-type "illegal-status" is not supported'],
289
+			['john.doe', 'online', 50, true, true, true, false, false, null, null],
290
+			['john.doe', 'online', 50, true, false, true, false, false, null, null],
291
+			['john.doe', 'online', 50, false, true, true, false, false, null, null],
292
+			['john.doe', 'online', 50, false, false, true, false, false, null, null],
293
+			['john.doe', 'online', null, true, true, true, true, false, null, null],
294
+			['john.doe', 'online', null, true, false, true, true, false, null, null],
295
+			['john.doe', 'online', null, false, true, true, true, false, null, null],
296
+			['john.doe', 'online', null, false, false, true, true, false, null, null],
297
+
298
+			['john.doe', 'away', 50, true, true, true, false, false, null, null],
299
+			['john.doe', 'away', 50, true, false, true, false, false, null, null],
300
+			['john.doe', 'away', 50, false, true, true, false, false, null, null],
301
+			['john.doe', 'away', 50, false, false, true, false, false, null, null],
302
+			['john.doe', 'away', null, true, true, true, true, false, null, null],
303
+			['john.doe', 'away', null, true, false, true, true, false, null, null],
304
+			['john.doe', 'away', null, false, true, true, true, false, null, null],
305
+			['john.doe', 'away', null, false, false, true, true, false, null, null],
306
+
307
+			['john.doe', 'dnd', 50, true, true, true, false, false, null, null],
308
+			['john.doe', 'dnd', 50, true, false, true, false, false, null, null],
309
+			['john.doe', 'dnd', 50, false, true, true, false, false, null, null],
310
+			['john.doe', 'dnd', 50, false, false, true, false, false, null, null],
311
+			['john.doe', 'dnd', null, true, true, true, true, false, null, null],
312
+			['john.doe', 'dnd', null, true, false, true, true, false, null, null],
313
+			['john.doe', 'dnd', null, false, true, true, true, false, null, null],
314
+			['john.doe', 'dnd', null, false, false, true, true, false, null, null],
315
+
316
+			['john.doe', 'invisible', 50, true, true, true, false, false, null, null],
317
+			['john.doe', 'invisible', 50, true, false, true, false, false, null, null],
318
+			['john.doe', 'invisible', 50, false, true, true, false, false, null, null],
319
+			['john.doe', 'invisible', 50, false, false, true, false, false, null, null],
320
+			['john.doe', 'invisible', null, true, true, true, true, false, null, null],
321
+			['john.doe', 'invisible', null, true, false, true, true, false, null, null],
322
+			['john.doe', 'invisible', null, false, true, true, true, false, null, null],
323
+			['john.doe', 'invisible', null, false, false, true, true, false, null, null],
324
+
325
+			['john.doe', 'offline', 50, true, true, true, false, false, null, null],
326
+			['john.doe', 'offline', 50, true, false, true, false, false, null, null],
327
+			['john.doe', 'offline', 50, false, true, true, false, false, null, null],
328
+			['john.doe', 'offline', 50, false, false, true, false, false, null, null],
329
+			['john.doe', 'offline', null, true, true, true, true, false, null, null],
330
+			['john.doe', 'offline', null, true, false, true, true, false, null, null],
331
+			['john.doe', 'offline', null, false, true, true, true, false, null, null],
332
+			['john.doe', 'offline', null, false, false, true, true, false, null, null],
333
+
334
+			['john.doe', 'illegal-status', 50, true, true, false, false, true, InvalidStatusTypeException::class, 'Status-type "illegal-status" is not supported'],
335
+			['john.doe', 'illegal-status', 50, true, false, false, false, true, InvalidStatusTypeException::class, 'Status-type "illegal-status" is not supported'],
336
+			['john.doe', 'illegal-status', 50, false, true, false, false, true, InvalidStatusTypeException::class, 'Status-type "illegal-status" is not supported'],
337
+			['john.doe', 'illegal-status', 50, false, false, false, false, true, InvalidStatusTypeException::class, 'Status-type "illegal-status" is not supported'],
338
+			['john.doe', 'illegal-status', null, true, true, false, true, true, InvalidStatusTypeException::class, 'Status-type "illegal-status" is not supported'],
339
+			['john.doe', 'illegal-status', null, true, false, false, true, true, InvalidStatusTypeException::class, 'Status-type "illegal-status" is not supported'],
340
+			['john.doe', 'illegal-status', null, false, true, false, true, true, InvalidStatusTypeException::class, 'Status-type "illegal-status" is not supported'],
341
+			['john.doe', 'illegal-status', null, false, false, false, true, true, InvalidStatusTypeException::class, 'Status-type "illegal-status" is not supported'],
342 342
 		];
343 343
 	}
344 344
 
@@ -418,12 +418,12 @@  discard block
 block discarded – undo
418 418
 
419 419
 	public static function setPredefinedMessageDataProvider(): array {
420 420
 		return [
421
-			['john.doe', 'sick-leave', true, null, true,  true,  false, null, null],
422
-			['john.doe', 'sick-leave', true, null, false, true,  false, null, null],
423
-			['john.doe', 'sick-leave', true, 20,   true,  false, true,  InvalidClearAtException::class, 'ClearAt is in the past'],
424
-			['john.doe', 'sick-leave', true, 20,   false, false, true,  InvalidClearAtException::class, 'ClearAt is in the past'],
425
-			['john.doe', 'sick-leave', true, 60,   true,  true,  false, null, null],
426
-			['john.doe', 'sick-leave', true, 60,   false, true,  false, null, null],
421
+			['john.doe', 'sick-leave', true, null, true, true, false, null, null],
422
+			['john.doe', 'sick-leave', true, null, false, true, false, null, null],
423
+			['john.doe', 'sick-leave', true, 20, true, false, true, InvalidClearAtException::class, 'ClearAt is in the past'],
424
+			['john.doe', 'sick-leave', true, 20, false, false, true, InvalidClearAtException::class, 'ClearAt is in the past'],
425
+			['john.doe', 'sick-leave', true, 60, true, true, false, null, null],
426
+			['john.doe', 'sick-leave', true, 60, false, true, false, null, null],
427 427
 			['john.doe', 'illegal-message-id', false, null, true, false, true, InvalidMessageIdException::class, 'Message-Id "illegal-message-id" is not supported'],
428 428
 			['john.doe', 'illegal-message-id', false, null, false, false, true, InvalidMessageIdException::class, 'Message-Id "illegal-message-id" is not supported'],
429 429
 		];
@@ -504,17 +504,17 @@  discard block
 block discarded – undo
504 504
 
505 505
 	public static function setCustomMessageDataProvider(): array {
506 506
 		return [
507
-			['john.doe', '
Please login to merge, or discard this patch.
apps/user_status/tests/Unit/Service/PredefinedStatusServiceTest.php 1 patch
Indentation   +155 added lines, -155 removed lines patch added patch discarded remove patch
@@ -14,159 +14,159 @@
 block discarded – undo
14 14
 use Test\TestCase;
15 15
 
16 16
 class PredefinedStatusServiceTest extends TestCase {
17
-	protected IL10N&MockObject $l10n;
18
-	protected PredefinedStatusService $service;
19
-
20
-	protected function setUp(): void {
21
-		parent::setUp();
22
-
23
-		$this->l10n = $this->createMock(IL10N::class);
24
-
25
-		$this->service = new PredefinedStatusService($this->l10n);
26
-	}
27
-
28
-	public function testGetDefaultStatuses(): void {
29
-		$this->l10n->expects($this->exactly(7))
30
-			->method('t')
31
-			->willReturnCallback(function ($text, $parameters = []) {
32
-				return vsprintf($text, $parameters);
33
-			});
34
-
35
-		$actual = $this->service->getDefaultStatuses();
36
-		$this->assertEquals([
37
-			[
38
-				'id' => 'meeting',
39
-				'icon' => '
Please login to merge, or discard this patch.
apps/user_status/tests/Unit/Listener/UserLiveStatusListenerTest.php 1 patch
Indentation   +123 added lines, -123 removed lines patch added patch discarded remove patch
@@ -23,127 +23,127 @@
 block discarded – undo
23 23
 use Test\TestCase;
24 24
 
25 25
 class UserLiveStatusListenerTest extends TestCase {
26
-	private UserStatusMapper&MockObject $mapper;
27
-	private StatusService&MockObject $statusService;
28
-	private ITimeFactory&MockObject $timeFactory;
29
-	private CalendarStatusService&MockObject $calendarStatusService;
30
-
31
-	private LoggerInterface&MockObject $logger;
32
-	private UserLiveStatusListener $listener;
33
-
34
-	protected function setUp(): void {
35
-		parent::setUp();
36
-
37
-		$this->mapper = $this->createMock(UserStatusMapper::class);
38
-		$this->statusService = $this->createMock(StatusService::class);
39
-		$this->timeFactory = $this->createMock(ITimeFactory::class);
40
-		$this->calendarStatusService = $this->createMock(CalendarStatusService::class);
41
-		$this->logger = $this->createMock(LoggerInterface::class);
42
-
43
-		$this->listener = new UserLiveStatusListener(
44
-			$this->mapper,
45
-			$this->statusService,
46
-			$this->timeFactory,
47
-			$this->calendarStatusService,
48
-			$this->logger,
49
-		);
50
-	}
51
-
52
-	#[\PHPUnit\Framework\Attributes\DataProvider('handleEventWithCorrectEventDataProvider')]
53
-	public function testHandleWithCorrectEvent(
54
-		string $userId,
55
-		string $previousStatus,
56
-		int $previousTimestamp,
57
-		bool $previousIsUserDefined,
58
-		string $eventStatus,
59
-		int $eventTimestamp,
60
-		bool $expectExisting,
61
-		bool $expectUpdate,
62
-	): void {
63
-		$userStatus = new UserStatus();
64
-
65
-		if ($expectExisting) {
66
-			$userStatus->setId(42);
67
-			$userStatus->setUserId($userId);
68
-			$userStatus->setStatus($previousStatus);
69
-			$userStatus->setStatusTimestamp($previousTimestamp);
70
-			$userStatus->setIsUserDefined($previousIsUserDefined);
71
-
72
-			$this->statusService->expects($this->once())
73
-				->method('findByUserId')
74
-				->with($userId)
75
-				->willReturn($userStatus);
76
-		} else {
77
-			$this->statusService->expects($this->once())
78
-				->method('findByUserId')
79
-				->with($userId)
80
-				->willThrowException(new DoesNotExistException(''));
81
-		}
82
-
83
-		$user = $this->createMock(IUser::class);
84
-		$user->method('getUID')->willReturn($userId);
85
-		$event = new UserLiveStatusEvent($user, $eventStatus, $eventTimestamp);
86
-
87
-		$this->timeFactory->expects($this->atMost(1))
88
-			->method('getTime')
89
-			->willReturn(5000);
90
-
91
-		if ($expectUpdate) {
92
-			if ($expectExisting) {
93
-				$this->mapper->expects($this->never())
94
-					->method('insert');
95
-				$this->mapper->expects($this->once())
96
-					->method('update')
97
-					->with($this->callback(function ($userStatus) use ($eventStatus, $eventTimestamp) {
98
-						$this->assertEquals($eventStatus, $userStatus->getStatus());
99
-						$this->assertEquals($eventTimestamp, $userStatus->getStatusTimestamp());
100
-						$this->assertFalse($userStatus->getIsUserDefined());
101
-
102
-						return true;
103
-					}));
104
-			} else {
105
-				$this->mapper->expects($this->once())
106
-					->method('insert')
107
-					->with($this->callback(function ($userStatus) use ($eventStatus, $eventTimestamp) {
108
-						$this->assertEquals($eventStatus, $userStatus->getStatus());
109
-						$this->assertEquals($eventTimestamp, $userStatus->getStatusTimestamp());
110
-						$this->assertFalse($userStatus->getIsUserDefined());
111
-
112
-						return true;
113
-					}));
114
-				$this->mapper->expects($this->never())
115
-					->method('update');
116
-			}
117
-
118
-			$this->listener->handle($event);
119
-		} else {
120
-			$this->mapper->expects($this->never())
121
-				->method('insert');
122
-			$this->mapper->expects($this->never())
123
-				->method('update');
124
-
125
-			$this->listener->handle($event);
126
-		}
127
-	}
128
-
129
-	public static function handleEventWithCorrectEventDataProvider(): array {
130
-		return [
131
-			['john.doe', 'offline', 0, false, 'online', 5000, true, true],
132
-			['john.doe', 'offline', 0, false, 'online', 5000, false, true],
133
-			['john.doe', 'online', 5000, false, 'online', 5000, true, false],
134
-			['john.doe', 'online', 5000, false, 'online', 5000, false, true],
135
-			['john.doe', 'away', 5000, false, 'online', 5000, true, true],
136
-			['john.doe', 'online', 5000, false, 'away', 5000, true, false],
137
-			['john.doe', 'away', 5000, true, 'online', 5000, true, false],
138
-			['john.doe', 'online', 5000, true, 'away', 5000, true, false],
139
-		];
140
-	}
141
-
142
-	public function testHandleWithWrongEvent(): void {
143
-		$this->mapper->expects($this->never())
144
-			->method('insertOrUpdate');
145
-
146
-		$event = new GenericEvent();
147
-		$this->listener->handle($event);
148
-	}
26
+    private UserStatusMapper&MockObject $mapper;
27
+    private StatusService&MockObject $statusService;
28
+    private ITimeFactory&MockObject $timeFactory;
29
+    private CalendarStatusService&MockObject $calendarStatusService;
30
+
31
+    private LoggerInterface&MockObject $logger;
32
+    private UserLiveStatusListener $listener;
33
+
34
+    protected function setUp(): void {
35
+        parent::setUp();
36
+
37
+        $this->mapper = $this->createMock(UserStatusMapper::class);
38
+        $this->statusService = $this->createMock(StatusService::class);
39
+        $this->timeFactory = $this->createMock(ITimeFactory::class);
40
+        $this->calendarStatusService = $this->createMock(CalendarStatusService::class);
41
+        $this->logger = $this->createMock(LoggerInterface::class);
42
+
43
+        $this->listener = new UserLiveStatusListener(
44
+            $this->mapper,
45
+            $this->statusService,
46
+            $this->timeFactory,
47
+            $this->calendarStatusService,
48
+            $this->logger,
49
+        );
50
+    }
51
+
52
+    #[\PHPUnit\Framework\Attributes\DataProvider('handleEventWithCorrectEventDataProvider')]
53
+    public function testHandleWithCorrectEvent(
54
+        string $userId,
55
+        string $previousStatus,
56
+        int $previousTimestamp,
57
+        bool $previousIsUserDefined,
58
+        string $eventStatus,
59
+        int $eventTimestamp,
60
+        bool $expectExisting,
61
+        bool $expectUpdate,
62
+    ): void {
63
+        $userStatus = new UserStatus();
64
+
65
+        if ($expectExisting) {
66
+            $userStatus->setId(42);
67
+            $userStatus->setUserId($userId);
68
+            $userStatus->setStatus($previousStatus);
69
+            $userStatus->setStatusTimestamp($previousTimestamp);
70
+            $userStatus->setIsUserDefined($previousIsUserDefined);
71
+
72
+            $this->statusService->expects($this->once())
73
+                ->method('findByUserId')
74
+                ->with($userId)
75
+                ->willReturn($userStatus);
76
+        } else {
77
+            $this->statusService->expects($this->once())
78
+                ->method('findByUserId')
79
+                ->with($userId)
80
+                ->willThrowException(new DoesNotExistException(''));
81
+        }
82
+
83
+        $user = $this->createMock(IUser::class);
84
+        $user->method('getUID')->willReturn($userId);
85
+        $event = new UserLiveStatusEvent($user, $eventStatus, $eventTimestamp);
86
+
87
+        $this->timeFactory->expects($this->atMost(1))
88
+            ->method('getTime')
89
+            ->willReturn(5000);
90
+
91
+        if ($expectUpdate) {
92
+            if ($expectExisting) {
93
+                $this->mapper->expects($this->never())
94
+                    ->method('insert');
95
+                $this->mapper->expects($this->once())
96
+                    ->method('update')
97
+                    ->with($this->callback(function ($userStatus) use ($eventStatus, $eventTimestamp) {
98
+                        $this->assertEquals($eventStatus, $userStatus->getStatus());
99
+                        $this->assertEquals($eventTimestamp, $userStatus->getStatusTimestamp());
100
+                        $this->assertFalse($userStatus->getIsUserDefined());
101
+
102
+                        return true;
103
+                    }));
104
+            } else {
105
+                $this->mapper->expects($this->once())
106
+                    ->method('insert')
107
+                    ->with($this->callback(function ($userStatus) use ($eventStatus, $eventTimestamp) {
108
+                        $this->assertEquals($eventStatus, $userStatus->getStatus());
109
+                        $this->assertEquals($eventTimestamp, $userStatus->getStatusTimestamp());
110
+                        $this->assertFalse($userStatus->getIsUserDefined());
111
+
112
+                        return true;
113
+                    }));
114
+                $this->mapper->expects($this->never())
115
+                    ->method('update');
116
+            }
117
+
118
+            $this->listener->handle($event);
119
+        } else {
120
+            $this->mapper->expects($this->never())
121
+                ->method('insert');
122
+            $this->mapper->expects($this->never())
123
+                ->method('update');
124
+
125
+            $this->listener->handle($event);
126
+        }
127
+    }
128
+
129
+    public static function handleEventWithCorrectEventDataProvider(): array {
130
+        return [
131
+            ['john.doe', 'offline', 0, false, 'online', 5000, true, true],
132
+            ['john.doe', 'offline', 0, false, 'online', 5000, false, true],
133
+            ['john.doe', 'online', 5000, false, 'online', 5000, true, false],
134
+            ['john.doe', 'online', 5000, false, 'online', 5000, false, true],
135
+            ['john.doe', 'away', 5000, false, 'online', 5000, true, true],
136
+            ['john.doe', 'online', 5000, false, 'away', 5000, true, false],
137
+            ['john.doe', 'away', 5000, true, 'online', 5000, true, false],
138
+            ['john.doe', 'online', 5000, true, 'away', 5000, true, false],
139
+        ];
140
+    }
141
+
142
+    public function testHandleWithWrongEvent(): void {
143
+        $this->mapper->expects($this->never())
144
+            ->method('insertOrUpdate');
145
+
146
+        $event = new GenericEvent();
147
+        $this->listener->handle($event);
148
+    }
149 149
 }
Please login to merge, or discard this patch.