Completed
Push — stable8.2 ( e9036a...6707df )
by
unknown
59:39
created

ObjectTree::testGetNodeForPathRoot()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 23
Code Lines 15

Duplication

Lines 23
Ratio 100 %
Metric Value
dl 23
loc 23
rs 9.0857
cc 1
eloc 15
nc 1
nop 0
1
<?php
2
/**
3
 * Copyright (c) 2013 Thomas Müller <[email protected]>
4
 * This file is licensed under the Affero General Public License version 3 or
5
 * later.
6
 * See the COPYING-README file.
7
 */
8
9
namespace Test\OC\Connector\Sabre;
10
11
12
use OC\Files\FileInfo;
13
use OC\Connector\Sabre\Directory;
14
use OC\Files\Storage\Temporary;
15
16
class TestDoubleFileView extends \OC\Files\View {
17
18
	public function __construct($updatables, $deletables, $canRename = true) {
19
		$this->updatables = $updatables;
0 ignored issues
show
Bug introduced by
The property updatables does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
20
		$this->deletables = $deletables;
0 ignored issues
show
Bug introduced by
The property deletables does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
21
		$this->canRename = $canRename;
0 ignored issues
show
Bug introduced by
The property canRename does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
22
	}
23
24
	public function isUpdatable($path) {
25
		return $this->updatables[$path];
26
	}
27
28
	public function isCreatable($path) {
29
		return $this->updatables[$path];
30
	}
31
32
	public function isDeletable($path) {
33
		return $this->deletables[$path];
34
	}
35
36
	public function rename($path1, $path2) {
37
		return $this->canRename;
38
	}
39
40
	public function getRelativePath($path) {
41
		return $path;
42
	}
43
}
44
45
class ObjectTree extends \Test\TestCase {
46
47
	/**
48
	 * @dataProvider moveFailedProvider
49
	 * @expectedException \Sabre\DAV\Exception\Forbidden
50
	 */
51
	public function testMoveFailed($source, $destination, $updatables, $deletables) {
52
		$this->moveTest($source, $destination, $updatables, $deletables);
53
	}
54
55
	/**
56
	 * @dataProvider moveSuccessProvider
57
	 */
58
	public function testMoveSuccess($source, $destination, $updatables, $deletables) {
59
		$this->moveTest($source, $destination, $updatables, $deletables);
60
		$this->assertTrue(true);
61
	}
62
63
	/**
64
	 * @dataProvider moveFailedInvalidCharsProvider
65
	 * @expectedException \OC\Connector\Sabre\Exception\InvalidPath
66
	 */
67
	public function testMoveFailedInvalidChars($source, $destination, $updatables, $deletables) {
68
		$this->moveTest($source, $destination, $updatables, $deletables);
69
	}
70
71
	function moveFailedInvalidCharsProvider() {
1 ignored issue
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
72
		return array(
73
			array('a/b', 'a/*', array('a' => true, 'a/b' => true, 'a/c*' => false), array()),
74
		);
75
	}
76
77
	function moveFailedProvider() {
1 ignored issue
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
78
		return array(
79
			array('a/b', 'a/c', array('a' => false, 'a/b' => false, 'a/c' => false), array()),
80
			array('a/b', 'b/b', array('a' => false, 'a/b' => false, 'b' => false, 'b/b' => false), array()),
81
			array('a/b', 'b/b', array('a' => false, 'a/b' => true, 'b' => false, 'b/b' => false), array()),
82
			array('a/b', 'b/b', array('a' => true, 'a/b' => true, 'b' => false, 'b/b' => false), array()),
83
			array('a/b', 'b/b', array('a' => true, 'a/b' => true, 'b' => true, 'b/b' => false), array('a/b' => false)),
84
			array('a/b', 'a/c', array('a' => false, 'a/b' => true, 'a/c' => false), array()),
85
		);
86
	}
87
88
	function moveSuccessProvider() {
1 ignored issue
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
89
		return array(
90
			array('a/b', 'b/b', array('a' => true, 'a/b' => true, 'b' => true, 'b/b' => false), array('a/b' => true)),
91
			// older files with special chars can still be renamed to valid names
92
			array('a/b*', 'b/b', array('a' => true, 'a/b*' => true, 'b' => true, 'b/b' => false), array('a/b*' => true)),
93
		);
94
	}
95
96
	/**
97
	 * @param $source
98
	 * @param $destination
99
	 * @param $updatables
100
	 */
101
	private function moveTest($source, $destination, $updatables, $deletables) {
102
		$view = new TestDoubleFileView($updatables, $deletables);
103
104
		$info = new FileInfo('', null, null, array(), null);
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a object<OC\Files\Storage\Storage>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation introduced by
null is of type null, but the function expects a object<OCP\Files\Mount\IMountPoint>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
105
106
		$rootDir = new Directory($view, $info);
107
		$objectTree = $this->getMock('\OC\Connector\Sabre\ObjectTree',
108
			array('nodeExists', 'getNodeForPath'),
109
			array($rootDir, $view));
110
111
		$objectTree->expects($this->once())
112
			->method('getNodeForPath')
113
			->with($this->identicalTo($source))
114
			->will($this->returnValue(false));
115
116
		/** @var $objectTree \OC\Connector\Sabre\ObjectTree */
117
		$mountManager = \OC\Files\Filesystem::getMountManager();
118
		$objectTree->init($rootDir, $view, $mountManager);
119
		$objectTree->move($source, $destination);
120
	}
121
122
	/**
123
	 * @dataProvider nodeForPathProvider
124
	 */
125
	public function testGetNodeForPath(
126
		$inputFileName,
127
		$fileInfoQueryPath,
128
		$outputFileName,
129
		$type,
130
		$enableChunkingHeader
131
	) {
132
133
		if ($enableChunkingHeader) {
134
			$_SERVER['HTTP_OC_CHUNKED'] = true;
135
		}
136
137
		$rootNode = $this->getMockBuilder('\OC\Connector\Sabre\Directory')
138
			->disableOriginalConstructor()
139
			->getMock();
140
		$mountManager = $this->getMock('\OC\Files\Mount\Manager');
141
		$view = $this->getMock('\OC\Files\View');
142
		$fileInfo = $this->getMock('\OCP\Files\FileInfo');
143
		$fileInfo->expects($this->once())
144
			->method('getType')
145
			->will($this->returnValue($type));
146
		$fileInfo->expects($this->once())
147
			->method('getName')
148
			->will($this->returnValue($outputFileName));
149
150
		$view->expects($this->once())
151
			->method('getFileInfo')
152
			->with($fileInfoQueryPath)
153
			->will($this->returnValue($fileInfo));
154
155
		$tree = new \OC\Connector\Sabre\ObjectTree();
156
		$tree->init($rootNode, $view, $mountManager);
157
158
		$node = $tree->getNodeForPath($inputFileName);
159
160
		$this->assertNotNull($node);
161
		$this->assertEquals($outputFileName, $node->getName());
162
163
		if ($type === 'file') {
164
			$this->assertTrue($node instanceof \OC\Connector\Sabre\File);
165
		} else {
166
			$this->assertTrue($node instanceof \OC\Connector\Sabre\Directory);
167
		}
168
169
		unset($_SERVER['HTTP_OC_CHUNKED']);
170
	}
171
172
	function nodeForPathProvider() {
1 ignored issue
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
173
		return array(
174
			// regular file
175
			array(
176
				'regularfile.txt',
177
				'regularfile.txt',
178
				'regularfile.txt',
179
				'file',
180
				false
181
			),
182
			// regular directory
183
			array(
184
				'regulardir',
185
				'regulardir',
186
				'regulardir',
187
				'dir',
188
				false
189
			),
190
			// regular file with chunking
191
			array(
192
				'regularfile.txt',
193
				'regularfile.txt',
194
				'regularfile.txt',
195
				'file',
196
				true
197
			),
198
			// regular directory with chunking
199
			array(
200
				'regulardir',
201
				'regulardir',
202
				'regulardir',
203
				'dir',
204
				true
205
			),
206
			// file with chunky file name
207
			array(
208
				'regularfile.txt-chunking-123566789-10-1',
209
				'regularfile.txt',
210
				'regularfile.txt',
211
				'file',
212
				true
213
			),
214
			// regular file in subdir
215
			array(
216
				'subdir/regularfile.txt',
217
				'subdir/regularfile.txt',
218
				'regularfile.txt',
219
				'file',
220
				false
221
			),
222
			// regular directory in subdir
223
			array(
224
				'subdir/regulardir',
225
				'subdir/regulardir',
226
				'regulardir',
227
				'dir',
228
				false
229
			),
230
			// file with chunky file name in subdir
231
			array(
232
				'subdir/regularfile.txt-chunking-123566789-10-1',
233
				'subdir/regularfile.txt',
234
				'regularfile.txt',
235
				'file',
236
				true
237
			),
238
		);
239
	}
240
241
	/**
242
	 * @expectedException \OC\Connector\Sabre\Exception\InvalidPath
243
	 */
244 View Code Duplication
	public function testGetNodeForPathInvalidPath() {
245
		$path = '/foo\bar';
246
247
248
		$storage = new Temporary([]);
249
250
		$view = $this->getMock('\OC\Files\View', ['resolvePath']);
251
		$view->expects($this->once())
252
			->method('resolvePath')
253
			->will($this->returnCallback(function($path) use ($storage){
254
			return [$storage, ltrim($path, '/')];
255
		}));
256
257
		$rootNode = $this->getMockBuilder('\OC\Connector\Sabre\Directory')
258
			->disableOriginalConstructor()
259
			->getMock();
260
		$mountManager = $this->getMock('\OC\Files\Mount\Manager');
261
262
		$tree = new \OC\Connector\Sabre\ObjectTree();
263
		$tree->init($rootNode, $view, $mountManager);
264
265
		$tree->getNodeForPath($path);
266
	}
267
268 View Code Duplication
	public function testGetNodeForPathRoot() {
269
		$path = '/';
270
271
272
		$storage = new Temporary([]);
273
274
		$view = $this->getMock('\OC\Files\View', ['resolvePath']);
275
		$view->expects($this->any())
276
			->method('resolvePath')
277
			->will($this->returnCallback(function ($path) use ($storage) {
278
				return [$storage, ltrim($path, '/')];
279
			}));
280
281
		$rootNode = $this->getMockBuilder('\OC\Connector\Sabre\Directory')
282
			->disableOriginalConstructor()
283
			->getMock();
284
		$mountManager = $this->getMock('\OC\Files\Mount\Manager');
285
286
		$tree = new \OC\Connector\Sabre\ObjectTree();
287
		$tree->init($rootNode, $view, $mountManager);
288
289
		$this->assertInstanceOf('\Sabre\DAV\INode', $tree->getNodeForPath($path));
290
	}
291
292
	/**
293
	 * @expectedException \Sabre\DAV\Exception\Forbidden
294
	 * @expectedExceptionMessage Could not copy directory nameOfSourceNode, target exists
295
	 */
296
	public function testFailingMove() {
297
		$source = 'a/b';
298
		$destination = 'b/b';
299
		$updatables = array('a' => true, 'a/b' => true, 'b' => true, 'b/b' => false);
300
		$deletables = array('a/b' => true);
301
302
		$view = new TestDoubleFileView($updatables, $deletables);
303
304
		$info = new FileInfo('', null, null, array(), null);
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a object<OC\Files\Storage\Storage>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation introduced by
null is of type null, but the function expects a object<OCP\Files\Mount\IMountPoint>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
305
306
		$rootDir = new Directory($view, $info);
307
		$objectTree = $this->getMock('\OC\Connector\Sabre\ObjectTree',
308
			array('nodeExists', 'getNodeForPath'),
309
			array($rootDir, $view));
310
311
		$sourceNode = $this->getMockBuilder('\Sabre\DAV\ICollection')
312
			->disableOriginalConstructor()
313
			->getMock();
314
		$sourceNode->expects($this->once())
315
			->method('getName')
316
			->will($this->returnValue('nameOfSourceNode'));
317
318
		$objectTree->expects($this->once())
319
			->method('nodeExists')
320
			->with($this->identicalTo($destination))
321
			->will($this->returnValue(true));
322
		$objectTree->expects($this->once())
323
			->method('getNodeForPath')
324
			->with($this->identicalTo($source))
325
			->will($this->returnValue($sourceNode));
326
327
		/** @var $objectTree \OC\Connector\Sabre\ObjectTree */
328
		$mountManager = \OC\Files\Filesystem::getMountManager();
329
		$objectTree->init($rootDir, $view, $mountManager);
330
		$objectTree->move($source, $destination);
331
	}
332
}
333