Completed
Push — stable8.2 ( 696ee3...54f8ec )
by Roeland
70:33
created

Encryption::dataTestGetMetaData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
rs 9.4285
cc 1
eloc 6
nc 1
nop 0
1
<?php
2
3
namespace Test\Files\Storage\Wrapper;
4
5
use OC\Encryption\Util;
6
use OC\Files\Storage\Temporary;
7
use OC\Files\View;
8
use Test\Files\Storage\Storage;
9
10
class Encryption extends Storage {
11
12
	/**
13
	 * block size will always be 8192 for a PHP stream
14
	 * @see https://bugs.php.net/bug.php?id=21641
15
	 * @var integer
16
	 */
17
	protected $headerSize = 8192;
18
19
	/**
20
	 * @var Temporary
21
	 */
22
	private $sourceStorage;
23
24
	/**
25
	 * @var \OC\Files\Storage\Wrapper\Encryption | \PHPUnit_Framework_MockObject_MockObject
26
	 */
27
	protected $instance;
28
29
	/**
30
	 * @var \OC\Encryption\Keys\Storage | \PHPUnit_Framework_MockObject_MockObject
31
	 */
32
	private $keyStore;
33
34
	/**
35
	 * @var \OC\Encryption\Util | \PHPUnit_Framework_MockObject_MockObject
36
	 */
37
	private $util;
38
39
	/**
40
	 * @var \OC\Encryption\Manager | \PHPUnit_Framework_MockObject_MockObject
41
	 */
42
	private $encryptionManager;
43
44
	/**
45
	 * @var \OCP\Encryption\IEncryptionModule | \PHPUnit_Framework_MockObject_MockObject
46
	 */
47
	private $encryptionModule;
48
49
	/**
50
	 * @var \OC\Encryption\Update | \PHPUnit_Framework_MockObject_MockObject
51
	 */
52
	private $update;
53
54
	/**
55
	 * @var \OC\Files\Cache\Cache | \PHPUnit_Framework_MockObject_MockObject
56
	 */
57
	private $cache;
58
59
	/**
60
	 * @var \OC\Log | \PHPUnit_Framework_MockObject_MockObject
61
	 */
62
	private $logger;
63
64
	/**
65
	 * @var \OC\Encryption\File | \PHPUnit_Framework_MockObject_MockObject
66
	 */
67
	private $file;
68
69
70
	/**
71
	 * @var \OC\Files\Mount\MountPoint | \PHPUnit_Framework_MockObject_MockObject
72
	 */
73
	private $mount;
74
75
	/**
76
	 * @var \OC\Files\Mount\Manager | \PHPUnit_Framework_MockObject_MockObject
77
	 */
78
	private $mountManager;
79
80
	/**
81
	 * @var \OC\Group\Manager | \PHPUnit_Framework_MockObject_MockObject
82
	 */
83
	private $groupManager;
84
85
	/**
86
	 * @var \OCP\IConfig | \PHPUnit_Framework_MockObject_MockObject
87
	 */
88
	private $config;
89
90
91
	/** @var  integer dummy unencrypted size */
92
	private $dummySize = -1;
93
94
	protected function setUp() {
95
96
		parent::setUp();
97
98
		$mockModule = $this->buildMockModule();
99
		$this->encryptionManager = $this->getMockBuilder('\OC\Encryption\Manager')
100
			->disableOriginalConstructor()
101
			->setMethods(['getEncryptionModule', 'isEnabled'])
102
			->getMock();
103
		$this->encryptionManager->expects($this->any())
104
			->method('getEncryptionModule')
105
			->willReturn($mockModule);
106
107
		$this->config = $this->getMockBuilder('\OCP\IConfig')
108
			->disableOriginalConstructor()
109
			->getMock();
110
		$this->groupManager = $this->getMockBuilder('\OC\Group\Manager')
111
			->disableOriginalConstructor()
112
			->getMock();
113
114
		$this->util = $this->getMock('\OC\Encryption\Util',
115
			['getUidAndFilename', 'isFile', 'isExcluded'],
116
			[new View(), new \OC\User\Manager(), $this->groupManager, $this->config]);
117
		$this->util->expects($this->any())
118
			->method('getUidAndFilename')
119
			->willReturnCallback(function ($path) {
120
				return ['user1', $path];
121
			});
122
123
		$this->file = $this->getMockBuilder('\OC\Encryption\File')
124
			->disableOriginalConstructor()
125
			->setMethods(['getAccessList'])
126
			->getMock();
127
		$this->file->expects($this->any())->method('getAccessList')->willReturn([]);
128
129
		$this->logger = $this->getMock('\OC\Log');
130
131
		$this->sourceStorage = new Temporary(array());
132
133
		$this->keyStore = $this->getMockBuilder('\OC\Encryption\Keys\Storage')
134
			->disableOriginalConstructor()->getMock();
135
136
		$this->update = $this->getMockBuilder('\OC\Encryption\Update')
137
			->disableOriginalConstructor()->getMock();
138
139
		$this->mount = $this->getMockBuilder('\OC\Files\Mount\MountPoint')
140
			->disableOriginalConstructor()
141
			->setMethods(['getOption'])
142
			->getMock();
143
		$this->mount->expects($this->any())->method('getOption')->willReturnCallback(function ($option, $default) {
144
			if ($option === 'encrypt' && $default === true) {
145
				global $mockedMountPointEncryptionEnabled;
146
				if ($mockedMountPointEncryptionEnabled !== null) {
147
					return $mockedMountPointEncryptionEnabled;
148
				}
149
			}
150
			return true;
151
		});
152
153
		$this->cache = $this->getMockBuilder('\OC\Files\Cache\Cache')
154
			->disableOriginalConstructor()->getMock();
155
		$this->cache->expects($this->any())
156
			->method('get')
157
			->willReturnCallback(function($path) {return ['encrypted' => false, 'path' => $path];});
158
159
		$this->mountManager = $this->getMockBuilder('\OC\Files\Mount\Manager')
160
			->disableOriginalConstructor()->getMock();
161
162
		$this->instance = $this->getMockBuilder('\OC\Files\Storage\Wrapper\Encryption')
163
			->setConstructorArgs(
164
				[
165
					[
166
						'storage' => $this->sourceStorage,
167
						'root' => 'foo',
168
						'mountPoint' => '/',
169
						'mount' => $this->mount
170
					],
171
					$this->encryptionManager, $this->util, $this->logger, $this->file, null, $this->keyStore, $this->update, $this->mountManager
172
				]
173
			)
174
			->setMethods(['getMetaData', 'getCache', 'getEncryptionModule'])
175
			->getMock();
176
177
		$this->instance->expects($this->any())
178
			->method('getMetaData')
179
			->willReturnCallback(function ($path) {
180
				return ['encrypted' => true, 'size' => $this->dummySize, 'path' => $path];
181
			});
182
183
		$this->instance->expects($this->any())
184
			->method('getCache')
185
			->willReturn($this->cache);
186
187
		$this->instance->expects($this->any())
188
			->method('getEncryptionModule')
189
			->willReturn($mockModule);
190
	}
191
192
	/**
193
	 * @return \PHPUnit_Framework_MockObject_MockObject
194
	 */
195
	protected function buildMockModule() {
196
		$this->encryptionModule = $this->getMockBuilder('\OCP\Encryption\IEncryptionModule')
197
			->disableOriginalConstructor()
198
			->setMethods(['getId', 'getDisplayName', 'begin', 'end', 'encrypt', 'decrypt', 'update', 'shouldEncrypt', 'getUnencryptedBlockSize', 'isReadable', 'encryptAll', 'prepareDecryptAll'])
199
			->getMock();
200
201
		$this->encryptionModule->expects($this->any())->method('getId')->willReturn('UNIT_TEST_MODULE');
202
		$this->encryptionModule->expects($this->any())->method('getDisplayName')->willReturn('Unit test module');
203
		$this->encryptionModule->expects($this->any())->method('begin')->willReturn([]);
204
		$this->encryptionModule->expects($this->any())->method('end')->willReturn('');
205
		$this->encryptionModule->expects($this->any())->method('encrypt')->willReturnArgument(0);
206
		$this->encryptionModule->expects($this->any())->method('decrypt')->willReturnArgument(0);
207
		$this->encryptionModule->expects($this->any())->method('update')->willReturn(true);
208
		$this->encryptionModule->expects($this->any())->method('shouldEncrypt')->willReturn(true);
209
		$this->encryptionModule->expects($this->any())->method('getUnencryptedBlockSize')->willReturn(8192);
210
		$this->encryptionModule->expects($this->any())->method('isReadable')->willReturn(true);
211
		return $this->encryptionModule;
212
	}
213
214
	/**
215
	 * @dataProvider dataTestGetMetaData
216
	 *
217
	 * @param string $path
218
	 * @param array $metaData
219
	 * @param bool $encrypted
220
	 * @param bool $unencryptedSizeSet
221
	 * @param int $storedUnencryptedSize
222
	 * @param array $expected
223
	 */
224
	public function testGetMetaData($path, $metaData, $encrypted, $unencryptedSizeSet, $storedUnencryptedSize, $expected) {
225
226
		$sourceStorage = $this->getMockBuilder('\OC\Files\Storage\Storage')
227
			->disableOriginalConstructor()->getMock();
228
229
		$cache = $this->getMockBuilder('\OC\Files\Cache\Cache')
230
			->disableOriginalConstructor()->getMock();
231
		$cache->expects($this->any())
232
			->method('get')
233
			->willReturnCallback(
234
				function($path) use ($encrypted) {
235
					return ['encrypted' => $encrypted, 'path' => $path, 'size' => 0, 'fileid' => 1];
236
				}
237
			);
238
239
		$this->instance = $this->getMockBuilder('\OC\Files\Storage\Wrapper\Encryption')
240
			->setConstructorArgs(
241
				[
242
					[
243
						'storage' => $sourceStorage,
244
						'root' => 'foo',
245
						'mountPoint' => '/',
246
						'mount' => $this->mount
247
					],
248
					$this->encryptionManager, $this->util, $this->logger, $this->file, null, $this->keyStore, $this->update, $this->mountManager
249
				]
250
			)
251
			->setMethods(['getCache', 'verifyUnencryptedSize'])
252
			->getMock();
253
254
		if($unencryptedSizeSet) {
255
			$this->invokePrivate($this->instance, 'unencryptedSize', [[$path => $storedUnencryptedSize]]);
256
		}
257
258
259
		$sourceStorage->expects($this->once())->method('getMetaData')->with($path)
260
			->willReturn($metaData);
261
262
		$this->instance->expects($this->any())->method('getCache')->willReturn($cache);
263
		$this->instance->expects($this->any())->method('verifyUnencryptedSize')
264
			->with($path, 0)->willReturn($expected['size']);
265
266
		$result = $this->instance->getMetaData($path);
267
		$this->assertSame($expected['encrypted'], $result['encrypted']);
268
		$this->assertSame($expected['size'], $result['size']);
269
	}
270
271
	public function dataTestGetMetaData() {
272
		return [
273
			['/test.txt', ['size' => 42, 'encrypted' => false], true, true, 12, ['size' => 12, 'encrypted' => true]],
274
			['/test.txt', null, true, true, 12, null],
275
			['/test.txt', ['size' => 42, 'encrypted' => false], false, false, 12, ['size' => 42, 'encrypted' => false]],
276
			['/test.txt', ['size' => 42, 'encrypted' => false], true, false, 12, ['size' => 12, 'encrypted' => true]]
277
		];
278
	}
279
280
	public function testFilesize() {
281
		$cache = $this->getMockBuilder('\OC\Files\Cache\Cache')
282
			->disableOriginalConstructor()->getMock();
283
		$cache->expects($this->any())
284
			->method('get')
285
			->willReturn(['encrypted' => true, 'path' => '/test.txt', 'size' => 0, 'fileid' => 1]);
286
287
		$this->instance = $this->getMockBuilder('\OC\Files\Storage\Wrapper\Encryption')
288
			->setConstructorArgs(
289
				[
290
					[
291
						'storage' => $this->sourceStorage,
292
						'root' => 'foo',
293
						'mountPoint' => '/',
294
						'mount' => $this->mount
295
					],
296
					$this->encryptionManager, $this->util, $this->logger, $this->file, null, $this->keyStore, $this->update, $this->mountManager
297
				]
298
			)
299
			->setMethods(['getCache', 'verifyUnencryptedSize'])
300
			->getMock();
301
302
		$this->instance->expects($this->any())->method('getCache')->willReturn($cache);
303
		$this->instance->expects($this->any())->method('verifyUnencryptedSize')
304
			->willReturn(42);
305
306
307
		$this->assertSame(42,
308
			$this->instance->filesize('/test.txt')
309
		);
310
311
	}
312
313
	/**
314
	 * @dataProvider dataTestVerifyUnencryptedSize
315
	 *
316
	 * @param int $encryptedSize
317
	 * @param int $unencryptedSize
318
	 * @param bool $failure
319
	 * @param int $expected
320
	 */
321
	public function testVerifyUnencryptedSize($encryptedSize, $unencryptedSize, $failure, $expected) {
322
		$sourceStorage = $this->getMockBuilder('\OC\Files\Storage\Storage')
323
			->disableOriginalConstructor()->getMock();
324
325
		$this->instance = $this->getMockBuilder('\OC\Files\Storage\Wrapper\Encryption')
326
			->setConstructorArgs(
327
				[
328
					[
329
						'storage' => $sourceStorage,
330
						'root' => 'foo',
331
						'mountPoint' => '/',
332
						'mount' => $this->mount
333
					],
334
					$this->encryptionManager, $this->util, $this->logger, $this->file, null, $this->keyStore, $this->update, $this->mountManager
335
				]
336
			)
337
			->setMethods(['fixUnencryptedSize'])
338
			->getMock();
339
340
		$sourceStorage->expects($this->once())->method('filesize')->willReturn($encryptedSize);
341
342
		$this->instance->expects($this->any())->method('fixUnencryptedSize')
343
			->with('/test.txt', $encryptedSize, $unencryptedSize)
344
			->willReturnCallback(
345
				function() use ($failure, $expected) {
346
					if ($failure) {
347
						throw new \Exception();
348
					} else {
349
						return $expected;
350
					}
351
				}
352
			);
353
354
		$this->assertSame(
355
			$expected,
356
			$this->invokePrivate($this->instance, 'verifyUnencryptedSize', ['/test.txt', $unencryptedSize])
357
		);
358
	}
359
360
	public function dataTestVerifyUnencryptedSize() {
361
		return [
362
			[120, 80, false, 80],
363
			[120, 120, false, 80],
364
			[120, -1, false, 80],
365
			[120, -1, true, -1]
366
		];
367
	}
368
369
	/**
370
	 * @dataProvider dataTestCopyAndRename
371
	 *
372
	 * @param string $source
373
	 * @param string $target
374
	 * @param $encryptionEnabled
375
	 * @param boolean $renameKeysReturn
376
	 */
377
	public function testRename($source,
378
							   $target,
379
							   $encryptionEnabled,
380
							   $renameKeysReturn) {
381
		if ($encryptionEnabled) {
382
			$this->keyStore
383
				->expects($this->once())
384
				->method('renameKeys')
385
				->willReturn($renameKeysReturn);
386
		} else {
387
			$this->keyStore
388
				->expects($this->never())->method('renameKeys');
389
		}
390
		$this->util->expects($this->any())
391
			->method('isFile')->willReturn(true);
392
		$this->encryptionManager->expects($this->once())
393
			->method('isEnabled')->willReturn($encryptionEnabled);
394
395
		$this->instance->mkdir($source);
396
		$this->instance->mkdir(dirname($target));
397
		$this->instance->rename($source, $target);
398
	}
399
400
	public function testCopyEncryption() {
401
		$this->instance->file_put_contents('source.txt', 'bar');
402
		$this->instance->copy('source.txt', 'target.txt');
403
		$this->assertSame('bar', $this->instance->file_get_contents('target.txt'));
404
		$targetMeta = $this->instance->getMetaData('target.txt');
405
		$sourceMeta = $this->instance->getMetaData('source.txt');
406
		$this->assertSame($sourceMeta['encrypted'], $targetMeta['encrypted']);
407
		$this->assertSame($sourceMeta['size'], $targetMeta['size']);
408
	}
409
410
	/**
411
	 * data provider for testCopyTesting() and dataTestCopyAndRename()
412
	 *
413
	 * @return array
414
	 */
415
	public function dataTestCopyAndRename() {
416
		return array(
417
			array('source', 'target', true, false, false),
418
			array('source', 'target', true, true, false),
419
			array('source', '/subFolder/target', true, false, false),
420
			array('source', '/subFolder/target', true, true, true),
421
			array('source', '/subFolder/target', false, true, false),
422
		);
423
	}
424
425
	public function testIsLocal() {
426
		$this->encryptionManager->expects($this->once())
427
			->method('isEnabled')->willReturn(true);
428
		$this->assertFalse($this->instance->isLocal());
429
	}
430
431
	/**
432
	 * @dataProvider dataTestRmdir
433
	 *
434
	 * @param string $path
435
	 * @param boolean $rmdirResult
436
	 * @param boolean $isExcluded
437
	 * @param boolean $encryptionEnabled
438
	 */
439
	public function testRmdir($path, $rmdirResult, $isExcluded, $encryptionEnabled) {
440
		$sourceStorage = $this->getMockBuilder('\OC\Files\Storage\Storage')
441
			->disableOriginalConstructor()->getMock();
442
443
		$util = $this->getMockBuilder('\OC\Encryption\Util')->disableOriginalConstructor()->getMock();
444
445
		$sourceStorage->expects($this->once())->method('rmdir')->willReturn($rmdirResult);
446
		$util->expects($this->any())->method('isExcluded')-> willReturn($isExcluded);
447
		$this->encryptionManager->expects($this->any())->method('isEnabled')->willReturn($encryptionEnabled);
448
449
		$encryptionStorage = new \OC\Files\Storage\Wrapper\Encryption(
450
					[
451
						'storage' => $sourceStorage,
452
						'root' => 'foo',
453
						'mountPoint' => '/mountPoint',
454
						'mount' => $this->mount
455
					],
456
					$this->encryptionManager, $util, $this->logger, $this->file, null, $this->keyStore, $this->update
457
		);
458
459
460
		if ($rmdirResult === true && $isExcluded === false && $encryptionEnabled === true) {
461
			$this->keyStore->expects($this->once())->method('deleteAllFileKeys')->with('/mountPoint' . $path);
462
		} else {
463
			$this->keyStore->expects($this->never())->method('deleteAllFileKeys');
464
		}
465
466
		$encryptionStorage->rmdir($path);
467
	}
468
469
	public function dataTestRmdir() {
470
		return array(
471
			array('/file.txt', true, true, true),
472
			array('/file.txt', false, true, true),
473
			array('/file.txt', true, false, true),
474
			array('/file.txt', false, false, true),
475
			array('/file.txt', true, true, false),
476
			array('/file.txt', false, true, false),
477
			array('/file.txt', true, false, false),
478
			array('/file.txt', false, false, false),
479
		);
480
	}
481
482
	/**
483
	 * @dataProvider dataTestCopyKeys
484
	 *
485
	 * @param boolean $excluded
486
	 * @param boolean $expected
487
	 */
488
	public function testCopyKeys($excluded, $expected) {
489
		$this->util->expects($this->once())
490
			->method('isExcluded')
491
			->willReturn($excluded);
492
493
		if ($excluded) {
494
			$this->keyStore->expects($this->never())->method('copyKeys');
495
		} else {
496
			$this->keyStore->expects($this->once())->method('copyKeys')->willReturn(true);
497
		}
498
499
		$this->assertSame($expected,
500
			self::invokePrivate($this->instance, 'copyKeys', ['/source', '/target'])
501
		);
502
	}
503
504
	public function dataTestCopyKeys() {
505
		return array(
506
			array(true, false),
507
			array(false, true),
508
		);
509
	}
510
511
	/**
512
	 * @dataProvider dataTestGetHeader
513
	 *
514
	 * @param string $path
515
	 * @param bool $strippedPathExists
516
	 * @param string $strippedPath
517
	 */
518
	public function testGetHeader($path, $strippedPathExists, $strippedPath) {
519
520
		$sourceStorage = $this->getMockBuilder('\OC\Files\Storage\Storage')
521
			->disableOriginalConstructor()->getMock();
522
523
		$util = $this->getMockBuilder('\OC\Encryption\Util')
524
			->setConstructorArgs([new View(), new \OC\User\Manager(), $this->groupManager, $this->config])
525
			->getMock();
526
527
		$instance = $this->getMockBuilder('\OC\Files\Storage\Wrapper\Encryption')
528
			->setConstructorArgs(
529
				[
530
					[
531
						'storage' => $sourceStorage,
532
						'root' => 'foo',
533
						'mountPoint' => '/',
534
						'mount' => $this->mount
535
					],
536
					$this->encryptionManager, $util, $this->logger, $this->file, null, $this->keyStore, $this->update, $this->mountManager
537
				]
538
			)
539
			->setMethods(['readFirstBlock', 'parseRawHeader'])
540
			->getMock();
541
542
		$instance->expects($this->once())->method(('parseRawHeader'))
543
			->willReturn([Util::HEADER_ENCRYPTION_MODULE_KEY => 'OC_DEFAULT_MODULE']);
544
545
		if ($strippedPathExists) {
546
			$instance->expects($this->once())->method('readFirstBlock')
547
				->with($strippedPath)->willReturn('');
548
		} else {
549
			$instance->expects($this->once())->method('readFirstBlock')
550
				->with($path)->willReturn('');
551
		}
552
553
		$util->expects($this->once())->method('stripPartialFileExtension')
554
			->with($path)->willReturn($strippedPath);
555
		$sourceStorage->expects($this->once())
556
			->method('file_exists')
557
			->with($strippedPath)
558
			->willReturn($strippedPathExists);
559
560
		$this->invokePrivate($instance, 'getHeader', [$path]);
561
	}
562
563
	public function dataTestGetHeader() {
564
		return array(
565
			array('/foo/bar.txt', false, '/foo/bar.txt'),
566
			array('/foo/bar.txt.part', false, '/foo/bar.txt'),
567
			array('/foo/bar.txt.ocTransferId7437493.part', false, '/foo/bar.txt'),
568
			array('/foo/bar.txt.part', true, '/foo/bar.txt'),
569
			array('/foo/bar.txt.ocTransferId7437493.part', true, '/foo/bar.txt'),
570
		);
571
	}
572
573
	/**
574
	 * test if getHeader adds the default module correctly to the header for
575
	 * legacy files
576
	 *
577
	 * @dataProvider dataTestGetHeaderAddLegacyModule
578
	 */
579
	public function testGetHeaderAddLegacyModule($header, $isEncrypted, $expected) {
580
581
		$sourceStorage = $this->getMockBuilder('\OC\Files\Storage\Storage')
582
			->disableOriginalConstructor()->getMock();
583
584
		$util = $this->getMockBuilder('\OC\Encryption\Util')
585
			->setConstructorArgs([new View(), new \OC\User\Manager(), $this->groupManager, $this->config])
586
			->getMock();
587
588
		$cache = $this->getMockBuilder('\OC\Files\Cache\Cache')
589
			->disableOriginalConstructor()->getMock();
590
		$cache->expects($this->any())
591
			->method('get')
592
			->willReturnCallback(function($path) use ($isEncrypted) {return ['encrypted' => $isEncrypted, 'path' => $path];});
593
594
		$instance = $this->getMockBuilder('\OC\Files\Storage\Wrapper\Encryption')
595
			->setConstructorArgs(
596
				[
597
					[
598
						'storage' => $sourceStorage,
599
						'root' => 'foo',
600
						'mountPoint' => '/',
601
						'mount' => $this->mount
602
					],
603
					$this->encryptionManager, $util, $this->logger, $this->file, null, $this->keyStore, $this->update, $this->mountManager
604
				]
605
			)
606
			->setMethods(['readFirstBlock', 'parseRawHeader', 'getCache'])
607
			->getMock();
608
609
		$instance->expects($this->once())->method(('parseRawHeader'))->willReturn($header);
610
		$instance->expects($this->any())->method('getCache')->willReturn($cache);
611
612
		$result = $this->invokePrivate($instance, 'getHeader', ['test.txt']);
613
		$this->assertSameSize($expected, $result);
614
		foreach ($result as $key => $value) {
615
			$this->assertArrayHasKey($key, $expected);
616
			$this->assertSame($expected[$key], $value);
617
		}
618
	}
619
620
	public function dataTestGetHeaderAddLegacyModule() {
621
		return [
622
			[['cipher' => 'AES-128'], true, ['cipher' => 'AES-128', Util::HEADER_ENCRYPTION_MODULE_KEY => 'OC_DEFAULT_MODULE']],
623
			[[], true, [Util::HEADER_ENCRYPTION_MODULE_KEY => 'OC_DEFAULT_MODULE']],
624
			[[], false, []],
625
		];
626
	}
627
628
	/**
629
	 * @dataProvider dataTestParseRawHeader
630
	 */
631
	public function testParseRawHeader($rawHeader, $expected) {
632
		$instance = new \OC\Files\Storage\Wrapper\Encryption(
633
					[
634
						'storage' => $this->sourceStorage,
635
						'root' => 'foo',
636
						'mountPoint' => '/',
637
						'mount' => $this->mount
638
					],
639
					$this->encryptionManager, $this->util, $this->logger, $this->file, null, $this->keyStore, $this->update, $this->mountManager
640
641
			);
642
643
		$result = $this->invokePrivate($instance, 'parseRawHeader', [$rawHeader]);
644
		$this->assertSameSize($expected, $result);
645
		foreach ($result as $key => $value) {
646
			$this->assertArrayHasKey($key, $expected);
647
			$this->assertSame($expected[$key], $value);
648
		}
649
	}
650
651
	public function dataTestParseRawHeader() {
652
		return [
653
			[str_pad('HBEGIN:oc_encryption_module:0:HEND', $this->headerSize, '-', STR_PAD_RIGHT)
654
				, [Util::HEADER_ENCRYPTION_MODULE_KEY => '0']],
655
			[str_pad('HBEGIN:oc_encryption_module:0:custom_header:foo:HEND', $this->headerSize, '-', STR_PAD_RIGHT)
656
				, ['custom_header' => 'foo', Util::HEADER_ENCRYPTION_MODULE_KEY => '0']],
657
			[str_pad('HelloWorld', $this->headerSize, '-', STR_PAD_RIGHT), []],
658
			['', []],
659
			[str_pad('HBEGIN:oc_encryption_module:0', $this->headerSize, '-', STR_PAD_RIGHT)
660
				, []],
661
			[str_pad('oc_encryption_module:0:HEND', $this->headerSize, '-', STR_PAD_RIGHT)
662
				, []],
663
		];
664
	}
665
666 View Code Duplication
	public function dataCopyBetweenStorage() {
667
		return [
668
			[true, true, true],
669
			[true, false, false],
670
			[false, true, false],
671
			[false, false, false],
672
		];
673
	}
674
675
	/**
676
	 * @dataProvider dataCopyBetweenStorage
677
	 *
678
	 * @param bool $encryptionEnabled
679
	 * @param bool $mountPointEncryptionEnabled
680
	 * @param bool $expectedEncrypted
681
	 */
682
	public function testCopyBetweenStorage($encryptionEnabled, $mountPointEncryptionEnabled, $expectedEncrypted) {
683
		$storage2 = $this->getMockBuilder('OCP\Files\Storage')
684
			->disableOriginalConstructor()
685
			->getMock();
686
687
		$sourceInternalPath = $targetInternalPath = 'file.txt';
688
		$preserveMtime = $isRename = false;
689
690
		$storage2->expects($this->any())
691
			->method('fopen')
692
			->willReturnCallback(function($path, $mode) {
693
				$temp = \OC::$server->getTempManager();
694
				return fopen($temp->getTemporaryFile(), $mode);
695
			});
696
697
		$this->encryptionManager->expects($this->any())
698
			->method('isEnabled')
699
			->willReturn($encryptionEnabled);
700
701
		// FIXME can not overwrite the return after definition
702
//		$this->mount->expects($this->at(0))
703
//			->method('getOption')
704
//			->with('encrypt', true)
705
//			->willReturn($mountPointEncryptionEnabled);
706
		global $mockedMountPointEncryptionEnabled;
707
		$mockedMountPointEncryptionEnabled = $mountPointEncryptionEnabled;
708
709
		$this->cache->expects($this->once())
710
			->method('put')
711
			->with($sourceInternalPath, ['encrypted' => $expectedEncrypted]);
712
713
		$this->invokePrivate($this->instance, 'copyBetweenStorage', [$storage2, $sourceInternalPath, $targetInternalPath, $preserveMtime, $isRename]);
714
715
		$this->assertFalse(false);
716
	}
717
718
	/**
719
	 * @dataProvider dataTestCopyBetweenStorageVersions
720
	 *
721
	 * @param string $sourceInternalPath
722
	 * @param string $targetInternalPath
723
	 * @param bool $copyResult
724
	 * @param bool $encrypted
725
	 */
726
	public function  testCopyBetweenStorageVersions($sourceInternalPath, $targetInternalPath, $copyResult, $encrypted) {
727
728
		$sourceStorage = $this->getMockBuilder('OCP\Files\Storage')
729
			->disableOriginalConstructor()
730
			->getMock();
731
732
		$targetStorage = $this->getMockBuilder('OCP\Files\Storage')
733
			->disableOriginalConstructor()
734
			->getMock();
735
736
		$cache = $this->getMockBuilder('\OC\Files\Cache\Cache')
737
			->disableOriginalConstructor()->getMock();
738
739
		$mountPoint = '/mountPoint';
740
741
		/** @var \OC\Files\Storage\Wrapper\Encryption |\PHPUnit_Framework_MockObject_MockObject  $instance */
742
		$instance = $this->getMockBuilder('\OC\Files\Storage\Wrapper\Encryption')
743
			->setConstructorArgs(
744
				[
745
					[
746
						'storage' => $targetStorage,
747
						'root' => 'foo',
748
						'mountPoint' => $mountPoint,
749
						'mount' => $this->mount
750
					],
751
					$this->encryptionManager,
752
					$this->util,
753
					$this->logger,
754
					$this->file,
755
					null,
756
					$this->keyStore,
757
					$this->update,
758
					$this->mountManager
759
				]
760
			)
761
			->setMethods(['updateUnencryptedSize', 'getCache'])
762
			->getMock();
763
764
		$targetStorage->expects($this->once())->method('copyFromStorage')
765
			->with($sourceStorage, $sourceInternalPath, $targetInternalPath)
766
			->willReturn($copyResult);
767
768
		if ($copyResult) {
769
			$instance->expects($this->once())->method('getCache')
770
				->with('', $sourceStorage)
771
				->willReturn($cache);
772
			$cache->expects($this->once())->method('get')
773
				->with($sourceInternalPath)
774
				->willReturn(['encrypted' => $encrypted, 'size' => 42]);
775
			if ($encrypted) {
776
				$instance->expects($this->once())->method('updateUnencryptedSize')
777
					->with($mountPoint . $targetInternalPath, 42);
778
			} else {
779
				$instance->expects($this->never())->method('updateUnencryptedSize');
780
			}
781
		} else {
782
			$instance->expects($this->never())->method('updateUnencryptedSize');
783
		}
784
785
		$result = $this->invokePrivate(
786
			$instance,
787
			'copyBetweenStorage',
788
			[
789
				$sourceStorage,
790
				$sourceInternalPath,
791
				$targetInternalPath,
792
				false,
793
				false
794
			]
795
		);
796
797
		$this->assertSame($copyResult, $result);
798
	}
799
800
	public function dataTestCopyBetweenStorageVersions() {
801
		return [
802
			['/files/foo.txt', '/files_versions/foo.txt.768743', true, true],
803
			['/files/foo.txt', '/files_versions/foo.txt.768743', true, false],
804
			['/files/foo.txt', '/files_versions/foo.txt.768743', false, true],
805
			['/files/foo.txt', '/files_versions/foo.txt.768743', false, false],
806
			['/files_versions/foo.txt.6487634', '/files/foo.txt', true, true],
807
			['/files_versions/foo.txt.6487634', '/files/foo.txt', true, false],
808
			['/files_versions/foo.txt.6487634', '/files/foo.txt', false, true],
809
			['/files_versions/foo.txt.6487634', '/files/foo.txt', false, false],
810
811
		];
812
	}
813
814
	/**
815
	 * @dataProvider dataTestIsVersion
816
	 * @param string $path
817
	 * @param bool $expected
818
	 */
819
	public function testIsVersion($path, $expected) {
820
		$this->assertSame($expected,
821
			$this->invokePrivate($this->instance, 'isVersion', [$path])
822
		);
823
	}
824
825 View Code Duplication
	public function dataTestIsVersion() {
826
		return [
827
			['files_versions/foo', true],
828
			['/files_versions/foo', true],
829
			['//files_versions/foo', true],
830
			['files/versions/foo', false],
831
			['files/files_versions/foo', false],
832
			['files_versions_test/foo', false],
833
		];
834
	}
835
836
}
837