Completed
Pull Request — stable8.2 (#24508)
by Joas
11:24
created

avatarcontrollertest.php ➔ is_uploaded_file()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
/**
3
 * @author Roeland Jago Douma <[email protected]>
4
 *
5
 * @copyright Copyright (c) 2015, ownCloud, Inc.
6
 * @license AGPL-3.0
7
 *
8
 * This code is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Affero General Public License, version 3,
10
 * as published by the Free Software Foundation.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
 * GNU Affero General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Affero General Public License, version 3,
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
19
 *
20
 */
21
namespace OC\Core\Avatar;
22
23
use OC;
24
use OC\Core\Application;
25
use OCP\AppFramework\IAppContainer;
26
use OC\Files\Filesystem;
27
use OCP\AppFramework\Http;
28
use OCP\Image;
29
use OCP\Files\Folder;
30
use OCP\Files\File;
31
32
/**
33
 * Overwrite is_uploaded_file in this namespace to allow proper unit testing of 
34
 * the postAvatar call.
35
 */
36
function is_uploaded_file($filename) {
37
	return file_exists($filename);
38
}
39
40
/**
41
 * Class AvatarControllerTest
42
 *
43
 * @package OC\Core\Avatar
44
 */
45
class AvatarControllerTest extends \Test\TestCase {
46
47
	/** @var IAppContainer */
48
	private $container;
49
	/** @var string */
50
	private $user;
51
	/** @var string */
52
	private $oldUser; 
53
	/** @var AvatarController */
54
	private $avatarController;
55
	
56
	private $avatarMock;
57
58
	private $userMock;
59
60
	protected function setUp() {
61
		$app = new Application;
62
		$this->container = $app->getContainer();
63
		$this->container['AppName'] = 'core';
64
		$this->container['AvatarManager'] = $this->getMockBuilder('OCP\IAvatarManager')
65
			->disableOriginalConstructor()->getMock();
66
		$this->container['Cache'] = $this->getMockBuilder('OC\Cache\File')
67
			->disableOriginalConstructor()->getMock();
68
		$this->container['L10N'] = $this->getMockBuilder('OCP\IL10N')
69
			->disableOriginalConstructor()->getMock();
70
		$this->container['L10N']->method('t')->will($this->returnArgument(0));
71
		$this->container['UserManager'] = $this->getMockBuilder('OCP\IUserManager')
72
			->disableOriginalConstructor()->getMock();
73
		$this->container['UserSession'] = $this->getMockBuilder('OCP\IUserSession')
74
			->disableOriginalConstructor()->getMock();
75
		$this->container['Request'] = $this->getMockBuilder('OCP\IRequest')
76
			->disableOriginalConstructor()->getMock();
77
		$this->container['UserFolder'] = $this->getMockBuilder('OCP\Files\Folder')
78
			->disableOriginalConstructor()->getMock();
79
		$this->container['Logger'] = $this->getMockBuilder('OCP\ILogger')
80
			->disableOriginalConstructor()->getMock();
81
82
		$this->avatarMock = $this->getMockBuilder('OCP\IAvatar')
83
			->disableOriginalConstructor()->getMock();
84
		$this->userMock = $this->getMockBuilder('OCP\IUser')
85
			->disableOriginalConstructor()->getMock();
86
87
		$this->avatarController = $this->container['AvatarController'];
88
89
		// Store current User
90
		$this->oldUser = \OC_User::getUser();
91
92
		// Create a dummy user
93
		$this->user = $this->getUniqueID('user');
94
95
		OC::$server->getUserManager()->createUser($this->user, $this->user);
96
		$this->loginAsUser($this->user);
97
98
		// Configure userMock
99
		$this->userMock->method('getDisplayName')->willReturn($this->user);
100
		$this->userMock->method('getUID')->willReturn($this->user);
101
		$this->container['UserManager']->method('get')
102
			->willReturnMap([[$this->user, $this->userMock]]);
103
		$this->container['UserSession']->method('getUser')->willReturn($this->userMock);
104
105
	}
106
107
	public function tearDown() {
108
		\OC_Util::tearDownFS();
109
		\OC_User::setUserId('');
110
		Filesystem::tearDown();
111
		OC::$server->getUserManager()->get($this->user)->delete();
112
		\OC_User::setIncognitoMode(false);
113
		
114
		\OC::$server->getSession()->set('public_link_authenticated', '');
115
116
		// Set old user
117
		\OC_User::setUserId($this->oldUser);
118
		\OC_Util::setupFS($this->oldUser);
119
	}
120
121
	/**
122
	 * Fetch an avatar if a user has no avatar
123
	 */
124
	public function testGetAvatarNoAvatar() {
125
		$this->container['AvatarManager']->method('getAvatar')->willReturn($this->avatarMock);
126
		$response = $this->avatarController->getAvatar($this->user, 32);
127
128
		//Comment out until JS is fixed
129
		//$this->assertEquals(Http::STATUS_NOT_FOUND, $response->getStatus());
130
		$this->assertEquals(Http::STATUS_OK, $response->getStatus());
131
		$this->assertEquals($this->user, $response->getData()['data']['displayname']);
132
	}
133
134
	/**
135
	 * Fetch the user's avatar
136
	 */
137
	public function testGetAvatar() {
138
		$image = new Image(OC::$SERVERROOT.'/tests/data/testimage.jpg');
139
		$this->avatarMock->method('get')->willReturn($image);
140
		$this->container['AvatarManager']->method('getAvatar')->willReturn($this->avatarMock);
141
142
		$response = $this->avatarController->getAvatar($this->user, 32);
143
144
		$this->assertEquals(Http::STATUS_OK, $response->getStatus());
145
146
		$image2 = new Image($response->getData());
147
		$this->assertEquals($image->mimeType(), $image2->mimeType());
148
		$this->assertEquals(crc32($response->getData()), $response->getEtag());
149
	}
150
151
	/**
152
	 * Fetch the avatar of a non-existing user
153
	 */
154
	public function testGetAvatarNoUser() {
155
		$this->avatarMock->method('get')->willReturn(null);
156
		$this->container['AvatarManager']->method('getAvatar')->willReturn($this->avatarMock);
157
158
		$response = $this->avatarController->getAvatar($this->user . 'doesnotexist', 32);
159
160
		//Comment out until JS is fixed
161
		//$this->assertEquals(Http::STATUS_NOT_FOUND, $response->getStatus());
162
		$this->assertEquals(Http::STATUS_OK, $response->getStatus());
163
		$this->assertEquals('', $response->getData()['data']['displayname']);
164
	}
165
166
	/**
167
	 * Make sure we get the correct size
168
	 */
169 View Code Duplication
	public function testGetAvatarSize() {
170
		$this->avatarMock->expects($this->once())
171
						 ->method('get')
172
						 ->with($this->equalTo(32));
173
174
		$this->container['AvatarManager']->method('getAvatar')->willReturn($this->avatarMock);
175
176
		$this->avatarController->getAvatar($this->user, 32);
177
	}
178
179
	/**
180
	 * We cannot get avatars that are 0 or negative
181
	 */
182 View Code Duplication
	public function testGetAvatarSizeMin() {
183
		$this->avatarMock->expects($this->once())
184
						 ->method('get')
185
						 ->with($this->equalTo(64));
186
187
		$this->container['AvatarManager']->method('getAvatar')->willReturn($this->avatarMock);
188
189
		$this->avatarController->getAvatar($this->user, 0);
190
	}
191
192
	/**
193
	 * We do not support avatars larger than 2048*2048
194
	 */
195 View Code Duplication
	public function testGetAvatarSizeMax() {
196
		$this->avatarMock->expects($this->once())
197
						 ->method('get')
198
						 ->with($this->equalTo(2048));
199
200
		$this->container['AvatarManager']->method('getAvatar')->willReturn($this->avatarMock);
201
202
		$this->avatarController->getAvatar($this->user, 2049);
203
	}
204
205
	/**
206
	 * Remove an avatar
207
	 */
208
	public function testDeleteAvatar() {
209
		$this->container['AvatarManager']->method('getAvatar')->willReturn($this->avatarMock);
210
211
		$response = $this->avatarController->deleteAvatar();
212
		$this->assertEquals(Http::STATUS_OK, $response->getStatus());
213
	}
214
215
	/**
216
	 * Test what happens if the removing of the avatar fails
217
	 */
218
	public function testDeleteAvatarException() {
219
		$this->avatarMock->method('remove')->will($this->throwException(new \Exception("foo")));
220
		$this->container['AvatarManager']->method('getAvatar')->willReturn($this->avatarMock);
221
222
		$this->container['Logger']->expects($this->once())
223
			->method('logException')
224
			->with(new \Exception("foo"));
225
		$expectedResponse = new Http\DataResponse(['data' => ['message' => 'An error occurred. Please contact your admin.']], Http::STATUS_BAD_REQUEST);
226
		$this->assertEquals($expectedResponse, $this->avatarController->deleteAvatar());
227
	}
228
229
	/**
230
	 * Trying to get a tmp avatar when it is not available. 404
231
	 */
232
	public function testTmpAvatarNoTmp() {
233
		$response = $this->avatarController->getTmpAvatar();
234
		$this->assertEquals(Http::STATUS_NOT_FOUND, $response->getStatus());
235
	}
236
237
	/**
238
	 * Fetch tmp avatar
239
	 */
240
	public function testTmpAvatarValid() {
241
		$this->container['Cache']->method('get')->willReturn(file_get_contents(OC::$SERVERROOT.'/tests/data/testimage.jpg'));
242
243
		$response = $this->avatarController->getTmpAvatar();
244
		$this->assertEquals(Http::STATUS_OK, $response->getStatus());
245
	}
246
247
248
	/**
249
	 * When trying to post a new avatar a path or image should be posted.
250
	 */
251
	public function testPostAvatarNoPathOrImage() {
252
		$response = $this->avatarController->postAvatar(null);
253
254
		$this->assertEquals(Http::STATUS_BAD_REQUEST, $response->getStatus());
255
	}
256
257
	/**
258
	 * Test a correct post of an avatar using POST
259
	 */
260 View Code Duplication
	public function testPostAvatarFile() {
261
		//Create temp file
262
		$fileName = tempnam(null, "avatarTest");
263
		$copyRes = copy(OC::$SERVERROOT.'/tests/data/testimage.jpg', $fileName);
264
		$this->assertTrue($copyRes);
265
266
		//Create file in cache
267
		$this->container['Cache']->method('get')->willReturn(file_get_contents(OC::$SERVERROOT.'/tests/data/testimage.jpg'));
268
269
		//Create request return
270
		$reqRet = ['error' => [0], 'tmp_name' => [$fileName], 'size' => [filesize(OC::$SERVERROOT.'/tests/data/testimage.jpg')]];
271
		$this->container['Request']->method('getUploadedFile')->willReturn($reqRet);
272
273
		$response = $this->avatarController->postAvatar(null);
274
275
		//On correct upload always respond with the notsquare message
276
		$this->assertEquals('notsquare', $response->getData()['data']);
277
278
		//File should be deleted
279
		$this->assertFalse(file_exists($fileName));
280
	}
281
282
	/**
283
	 * Test invalid post os an avatar using POST
284
	 */
285
	public function testPostAvatarInvalidFile() {
286
		//Create request return
287
		$reqRet = ['error' => [1], 'tmp_name' => ['foo']];
288
		$this->container['Request']->method('getUploadedFile')->willReturn($reqRet);
289
290
		$response = $this->avatarController->postAvatar(null);
291
292
		$this->assertEquals(Http::STATUS_BAD_REQUEST, $response->getStatus());
293
	}
294
295
	/**
296
	 * Check what happens when we upload a GIF
297
	 */
298 View Code Duplication
	public function testPostAvatarFileGif() {
299
		//Create temp file
300
		$fileName = tempnam(null, "avatarTest");
301
		$copyRes = copy(OC::$SERVERROOT.'/tests/data/testimage.gif', $fileName);
302
		$this->assertTrue($copyRes);
303
304
		//Create file in cache
305
		$this->container['Cache']->method('get')->willReturn(file_get_contents(OC::$SERVERROOT.'/tests/data/testimage.gif'));
306
307
		//Create request return
308
		$reqRet = ['error' => [0], 'tmp_name' => [$fileName], 'size' => filesize(OC::$SERVERROOT.'/tests/data/testimage.gif')];
309
		$this->container['Request']->method('getUploadedFile')->willReturn($reqRet);
310
311
		$response = $this->avatarController->postAvatar(null);
312
313
		$this->assertEquals('Unknown filetype', $response->getData()['data']['message']);
314
315
		//File should be deleted
316
		$this->assertFalse(file_exists($fileName));
317
	}
318
319
	/**
320
	 * Test posting avatar from existing file
321
	 */
322
	public function testPostAvatarFromFile() {
323
		//Mock node API call
324
		$file = $this->getMockBuilder('OCP\Files\File')
325
			->disableOriginalConstructor()->getMock();
326
		$file->method('getContent')->willReturn(file_get_contents(OC::$SERVERROOT.'/tests/data/testimage.jpg'));
327
		$this->container['UserFolder']->method('get')->willReturn($file);
328
329
		//Create request return
330
		$response = $this->avatarController->postAvatar('avatar.jpg');
331
332
		//On correct upload always respond with the notsquare message
333
		$this->assertEquals('notsquare', $response->getData()['data']);
334
	}
335
336
	/**
337
	 * Test what happens if the upload of the avatar fails
338
	 */
339
	public function testPostAvatarException() {
340
		$this->container['Cache']->expects($this->once())
341
			->method('set')
342
			->will($this->throwException(new \Exception("foo")));
343
		$file = $this->getMockBuilder('OCP\Files\File')
344
			->disableOriginalConstructor()->getMock();
345
		$file->method('getContent')->willReturn(file_get_contents(OC::$SERVERROOT.'/tests/data/testimage.jpg'));
346
		$this->container['UserFolder']->method('get')->willReturn($file);
347
348
		$this->container['Logger']->expects($this->once())
349
			->method('logException')
350
			->with(new \Exception("foo"));
351
		$expectedResponse = new Http\DataResponse(['data' => ['message' => 'An error occurred. Please contact your admin.']], Http::STATUS_OK);
352
		$this->assertEquals($expectedResponse, $this->avatarController->postAvatar('avatar.jpg'));
353
	}
354
355
356
	/**
357
	 * Test invalid crop argument
358
	 */
359
	public function testPostCroppedAvatarInvalidCrop() {
360
		$response = $this->avatarController->postCroppedAvatar([]);
361
362
		$this->assertEquals(Http::STATUS_BAD_REQUEST, $response->getStatus());
363
	}
364
365
	/**
366
	 * Test no tmp avatar to crop
367
	 */
368
	public function testPostCroppedAvatarNoTmpAvatar() {
369
		$response = $this->avatarController->postCroppedAvatar(['x' => 0, 'y' => 0, 'w' => 10, 'h' => 10]);
370
371
		$this->assertEquals(Http::STATUS_BAD_REQUEST, $response->getStatus());
372
	}
373
374
	/**
375
	 * Test with non square crop
376
	 */
377 View Code Duplication
	public function testPostCroppedAvatarNoSquareCrop() {
378
		$this->container['Cache']->method('get')->willReturn(file_get_contents(OC::$SERVERROOT.'/tests/data/testimage.jpg'));
379
380
		$this->avatarMock->method('set')->will($this->throwException(new \OC\NotSquareException));
381
		$this->container['AvatarManager']->method('getAvatar')->willReturn($this->avatarMock);
382
		$response = $this->avatarController->postCroppedAvatar(['x' => 0, 'y' => 0, 'w' => 10, 'h' => 11]);
383
384
		$this->assertEquals(Http::STATUS_BAD_REQUEST, $response->getStatus());
385
	}
386
387
	/**
388
	 * Check for proper reply on proper crop argument
389
	 */
390 View Code Duplication
	public function testPostCroppedAvatarValidCrop() {
391
		$this->container['Cache']->method('get')->willReturn(file_get_contents(OC::$SERVERROOT.'/tests/data/testimage.jpg'));
392
		$this->container['AvatarManager']->method('getAvatar')->willReturn($this->avatarMock);
393
		$response = $this->avatarController->postCroppedAvatar(['x' => 0, 'y' => 0, 'w' => 10, 'h' => 10]);
394
395
		$this->assertEquals(Http::STATUS_OK, $response->getStatus());
396
		$this->assertEquals('success', $response->getData()['status']);
397
	}
398
399
	/**
400
	 * Test what happens if the cropping of the avatar fails
401
	 */
402
	public function testPostCroppedAvatarException() {
403
		$this->container['Cache']->method('get')->willReturn(file_get_contents(OC::$SERVERROOT.'/tests/data/testimage.jpg'));
404
405
		$this->avatarMock->method('set')->will($this->throwException(new \Exception('foo')));
406
		$this->container['AvatarManager']->method('getAvatar')->willReturn($this->avatarMock);
407
408
		$this->container['Logger']->expects($this->once())
409
			->method('logException')
410
			->with(new \Exception('foo'));
411
		$expectedResponse = new Http\DataResponse(['data' => ['message' => 'An error occurred. Please contact your admin.']], Http::STATUS_BAD_REQUEST);
412
		$this->assertEquals($expectedResponse, $this->avatarController->postCroppedAvatar(['x' => 0, 'y' => 0, 'w' => 10, 'h' => 11]));
413
	}
414
415
416
	/**
417
	 * Check for proper reply on proper crop argument
418
	 */
419
	public function testFileTooBig() {
420
		$fileName = OC::$SERVERROOT.'/tests/data/testimage.jpg';
421
		//Create request return
422
		$reqRet = ['error' => [0], 'tmp_name' => [$fileName], 'size' => [21*1024*1024]];
423
		$this->container['Request']->method('getUploadedFile')->willReturn($reqRet);
424
425
		$response = $this->avatarController->postAvatar(null);
426
427
		$this->assertEquals('File is too big', $response->getData()['data']['message']);
428
	}
429
430
}
431