Test Failed
Pull Request — master (#33)
by Stephan
07:16
created

ProcessorTest::testValidateRawParameters()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 9.7
c 0
b 0
f 0
cc 2
nc 2
nop 5
1
<?php
2
3
namespace ParamProcessor\Tests;
4
5
use ParamProcessor\ProcessingError;
6
use ParamProcessor\ProcessingResult;
7
use ParamProcessor\Processor;
8
use ParamProcessor\Options;
9
10
/**
11
 * @covers ParamProcessor\Processor
12
 *
13
 * @licence GNU GPL v2+
14
 * @author Jeroen De Dauw < [email protected] >
15
 */
16
class ProcessorTest extends \PHPUnit_Framework_TestCase {
17
18
	public function testNewDefault() {
19
		$this->assertInstanceOf( 'ParamProcessor\Processor', Processor::newDefault() );
20
	}
21
22
	public function newFromOptionsProvider() {
23
		$options = [];
24
25
		$option = new Options();
26
27
		$options[] = clone $option;
28
29
		$option->setName( 'foobar' );
30
		$option->setLowercaseNames( false );
31
32
		$options[] = clone $option;
33
34
		return $this->arrayWrap( $options );
35
	}
36
37
	private function arrayWrap( array $elements ) {
38
		return array_map(
39
			function( $element ) {
40
				return [ $element ];
41
			},
42
			$elements
43
		);
44
	}
45
46
	public function testNewFromOptions() {
47
		$options = new Options();
48
		$validator = Processor::newFromOptions( clone $options );
49
		$this->assertInstanceOf( '\ParamProcessor\Processor', $validator );
50
		$this->assertEquals( $options, $validator->getOptions() );
51
	}
52
53
	/**
54
	 * Simple parameter definitions and values that should all pass.
55
	 *
56
	 * @return array
57
	 */
58
	private function getSimpleParams() {
59
		$params = [
60
			'awesome' => 'yes',
61
			'Howmuch ' => '9001',
62
			'FLOAT' => '4.2',
63
			' page' => 'Ohi there!',
64
			' text     ' => 'foo bar baz o_O',
65
		];
66
67
		$definitions = [
68
			'awesome' => [
69
				'type' => 'boolean',
70
			],
71
			'howmuch' => [
72
				'type' => 'integer',
73
			],
74
			'float' => [
75
				'type' => 'float',
76
			],
77
			'page' => [
78
				'type' => 'string',
79
				'hastoexist' => false,
80
			],
81
			'text' => [],
82
		];
83
84
		$options = new Options();
85
86
		$expected = [
87
			'awesome' => true,
88
			'howmuch' => 9001,
89
			'float' => 4.2,
90
			'page' => 'Ohi there!',
91
			'text' => 'foo bar baz o_O',
92
		];
93
94
		return [ $params, $definitions, $options, $expected ];
95
	}
96
97
	/**
98
	 * Simple parameter definitions with defaults and values
99
	 * that are invalid or missing and therefore default.
100
	 *
101
	 * @return array
102
	 */
103
	private function getDefaultingParams() {
104
		$params = [
105
			'awesome' => 'omg!',
106
			'howmuch' => 'omg!',
107
			'float' => 'omg!',
108
			'page' => 42,
109
			'whot?' => 'O_o',
110
			'integerr' => ' 9001 ',
111
		];
112
113
		$definitions = [
114
			'awesome' => [
115
				'type' => 'boolean',
116
				'default' => true,
117
			],
118
			'howmuch' => [
119
				'type' => 'integer',
120
				'default' => 9001,
121
			],
122
			'float' => [
123
				'type' => 'float',
124
				'default' => 4.2,
125
			],
126
			'page' => [
127
				'type' => 'string',
128
				'hastoexist' => false,
129
				'default' => 'Ohi there!',
130
			],
131
			'text' => [
132
				'default' => 'foo bar baz o_O',
133
			],
134
			'integerr' => [
135
				'type' => 'integer',
136
				'default' => 42,
137
			],
138
		];
139
140
		$options = new Options();
141
		$options->setTrimValues( false );
142
143
		$expected = [
144
			'awesome' => true,
145
			'howmuch' => 9001,
146
			'float' => 4.2,
147
			'page' => 'Ohi there!',
148
			'text' => 'foo bar baz o_O',
149
			'integerr' => 42,
150
		];
151
152
		return [ $params, $definitions, $options, $expected ];
153
	}
154
155
	/**
156
	 * Values and definitions in-system parameter handling.
157
	 * Options set to expect non-raw values.
158
	 *
159
	 * @return array
160
	 */
161
	private function getTypedParams() {
162
		$params = [
163
			'awesome' => true,
164
			'howmuch' => '42',
165
			'float' => 4.2,
166
			'page' => 'Ohi there!',
167
			'Text' => 'foo bar baz o_O',
168
			'text1 ' => 'foo bar baz o_O',
169
			' text2' => 'foo bar baz o_O',
170
		];
171
172
		$definitions = [
173
			'awesome' => [
174
				'type' => 'boolean',
175
			],
176
			'howmuch' => [
177
				'type' => 'integer',
178
				'default' => 9001,
179
			],
180
			'float' => [
181
				'type' => 'float',
182
				'lowerbound' => 9001,
183
				'default' => 9000.1
184
			],
185
			'page' => [
186
				'type' => 'string',
187
				'hastoexist' => false,
188
			],
189
			'text' => [
190
				'default' => 'some text',
191
			],
192
			'text1' => [
193
				'default' => 'some text',
194
			],
195
			'text2' => [
196
				'default' => 'some text',
197
			],
198
		];
199
200
		$options = new Options();
201
		$options->setRawStringInputs( false );
202
		$options->setLowercaseNames( false );
203
		$options->setTrimNames( false );
204
205
		$expected = [
206
			'awesome' => true,
207
			'howmuch' => 9001,
208
			'float' => 9000.1,
209
			'page' => 'Ohi there!',
210
			'text' => 'some text',
211
			'text1' => 'some text',
212
			'text2' => 'some text',
213
		];
214
215
		return [ $params, $definitions, $options, $expected ];
216
	}
217
218
	/**
219
	 * Values with capitalization and preceding/tailing spaces to test
220
	 * of the clean options work.
221
	 *
222
	 * @return array
223
	 */
224
	private function getUncleanParams() {
225
		$params = [
226
			'awesome' => ' yes ',
227
			'text' => ' FOO  bar  ',
228
			'integerr' => ' 9001 ',
229
		];
230
231
		$definitions = [
232
			'awesome' => [
233
				'type' => 'boolean',
234
			],
235
			'text' => [
236
				'default' => 'bar',
237
			],
238
			'integerr' => [
239
				'type' => 'integer',
240
				'default' => 42,
241
			],
242
		];
243
244
		$options = new Options();
245
		$options->setLowercaseValues( true );
246
		$options->setTrimValues( true );
247
248
		$expected = [
249
			'awesome' => true,
250
			'text' => 'foo  bar',
251
			'integerr' => 9001,
252
		];
253
254
		return [ $params, $definitions, $options, $expected ];
255
	}
256
257
	/**
258
	 * List parameters to test if list handling works correctly.
259
	 *
260
	 * @return array
261
	 */
262
	private function getListParams() {
263
		$params = [
264
			'awesome' => ' yes, no, on, off ',
265
			'float' => ' 9001 ; 42 ; 4.2;0',
266
		];
267
268
		$definitions = [
269
			'awesome' => [
270
				'type' => 'boolean',
271
				'islist' => true,
272
			],
273
			'text' => [
274
				'default' => [ 'bar' ],
275
				'islist' => true,
276
			],
277
			'float' => [
278
				'type' => 'float',
279
				'islist' => true,
280
				'delimiter' => ';'
281
			],
282
		];
283
284
		$options = new Options();
285
		$options->setLowercaseValues( true );
286
		$options->setTrimValues( true );
287
288
		$expected = [
289
			'awesome' => [ true, false, true, false ],
290
			'text' => [ 'bar' ],
291
			'float' => [ 9001.0, 42.0, 4.2, 0.0 ],
292
		];
293
294
		return [ $params, $definitions, $options, $expected ];
295
	}
296
297
	/**
298
	 * List parameters to test if list handling works correctly.
299
	 *
300
	 * @return array
301
	 */
302
	private function getPositionalParams() {
303
		$params = [
304
			' foobar ',
305
			' <span class="warning">Foobar!</span>',
306
		];
307
308
		$definitions = [
309
			'hugo' => [
310
				'type' => 'string',
311
			],
312
			'benno' => [
313
				'type' => 'string',
314
			],
315
		];
316
317
		$defaultParams = [ 'hugo', 'benno' ];
318
319
		$options = new Options();
320
		$options->setTrimValues( true );
321
322
		$expected = [
323
			'hugo' => 'foobar',
324
			'benno' => '<span class="warning">Foobar!</span>'
325
		];
326
327
		return [ $params, $definitions, $options, $expected, $defaultParams ];
328
	}
329
330
331
	protected function normalizeArgLists( &$argLists ) {
332
333
		foreach ( $argLists as &$argList ) {
334
			foreach ( $argList[ 1 ] as $key => &$definition ) {
335
				$definition[ 'message' ] = 'test-' . $key;
336
			}
337
338
			if ( !array_key_exists( 2, $argList ) ) {
339
				$argList[ 2 ] = new Options();
340
			}
341
		}
342
	}
343
344
	public function parameterProvider() {
345
		// $params, $definitions [, $options]
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
346
		$argLists = [];
347
348
		$argLists[] = $this->getSimpleParams();
349
350
		$argLists[] = $this->getDefaultingParams();
351
352
		$argLists[] = $this->getTypedParams();
353
354
		$argLists[] = $this->getUncleanParams();
355
356
		$argLists[] = $this->getListParams();
357
358
		$this->normalizeArgLists( $argLists );
359
360
		return $argLists;
361
	}
362
363
	public function rawParameterProvider() {
364
365
		$argLists = $this->parameterProvider();
366
367
		foreach ( $argLists as $i => $argList ) {
368
			$rawParams = [];
369
			foreach ( $argList[0] as $key => $value ) {
370
				if ( is_string( $key ) ) {
371
					$rawParams[] = "$key=$value";
372
				} else {
373
					$rawParams[] = $value;
374
				}
375
			}
376
			$argLists[$i][0] = $rawParams;
377
		}
378
379
		$rawArgLists = [];
380
381
		$rawArgLists[] = $this->getPositionalParams();
382
383
		$this->normalizeArgLists( $rawArgLists );
384
385
		return $argLists + $rawArgLists;
386
	}
387
388
	/**
389
	 * @dataProvider parameterProvider
390
	 */
391
	public function testSetParameters( array $params, array $definitions, Options $options ) {
392
		$validator = Processor::newFromOptions( $options );
393
394
		$validator->setParameters( $params, $definitions );
395
396
		$this->assertTrue( true ); // TODO
397
	}
398
399
	/**
400
	 * @dataProvider parameterProvider
401
	 */
402
	public function testValidateParameters( array $params, array $definitions, Options $options, array $expected = [] ) {
403
		$validator = Processor::newFromOptions( $options );
404
405
		$validator->setParameters( $params, $definitions );
406
407
		$processingResult = $validator->processParameters();
408
409
		$actualValues = [];
410
411
		foreach ( $processingResult->getParameters() as $param ) {
412
			$actualValues[$param->getName()] = $param->getValue();
413
		}
414
415
		$this->assertEquals( $expected, $actualValues );
416
417
418
	}
419
420
	/**
421
	 * @dataProvider rawParameterProvider
422
	 */
423
	public function testValidateRawParameters( array $params, array $definitions, Options $options, array $expected = [],  array $defaultParams = [] ) {
424
		$validator = Processor::newFromOptions( $options );
425
426
		$validator->setFunctionParams( $params, $definitions, $defaultParams );
427
428
		$processingResult = $validator->processParameters();
429
430
		$actualValues = [];
431
432
		foreach ( $processingResult->getParameters() as $param ) {
433
			$actualValues[$param->getName()] = $param->getValue();
434
		}
435
436
		$this->assertEquals( $expected, $actualValues );
437
438
439
	}
440
441
	public function testProcessParametersOnEmptyOptions() {
442
		$processor = Processor::newDefault();
443
444
		$this->assertInstanceOf(
445
			ProcessingResult::class,
446
			$processor->processParameters()
447
		);
448
	}
449
450
	public function testErrorsCanBeRetrievedAfterProcessing() {
451
		$processor = Processor::newDefault();
452
453
		$this->processWithOneError( $processor );
454
455
		$this->assertCount( 1, $processor->getErrors() );
456
	}
457
458
	private function processWithOneError( Processor $processor ) {
459
		$processor->setParameters(
460
			[],
461
			[
0 ignored issues
show
Documentation introduced by
array('awesome' => array...ge' => 'test-awesome')) is of type array<string,array<strin...ssage\":\"string\"}>"}>, but the function expects a array<integer,object<Par...ssor\IParamDefinition>>.

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...
462
				'awesome' => [
463
					'type' => 'boolean',
464
					'message' => 'test-awesome'
465
				],
466
			]
467
		);
468
469
		// There should be a single "missing required parameter" error.
470
		$processor->processParameters();
471
	}
472
473
	public function testErrorsAreClearedBetweenProcessingRuns() {
474
		$processor = Processor::newDefault();
475
476
		$this->processWithOneError( $processor );
477
		$processor->setParameters( [], [] );
478
		$processor->processParameters();
479
480
		$this->assertEmpty( $processor->getErrors() );
481
	}
482
483
}
484