function (Container $container) { /** @var GlobalSettingsProvider $actualGlobalSettingsProvider */ $actualGlobalSettingsProvider = $container->get('Piwik\Application\Kernel\GlobalSettingsProvider'); $config = self::makeTestConfig(); // copy over sections required for tests $config->tests = $actualGlobalSettingsProvider->getSection('tests'); $config->database = $actualGlobalSettingsProvider->getSection('database_tests'); return $config; }, ); } private static function makeTestConfig() { $settingsProvider = new GlobalSettingsProvider(null, self::getTestConfigFilePath()); $config = new Config($settingsProvider); // Add the first section. $sectionName = self::TEST_SECTION_1_NAME; $config->$sectionName[self::TEST_SETTING_1_1_NAME] = self::TEST_SETTING_1_1_VALUE; $config->$sectionName[self::TEST_SETTING_1_2_NAME] = self::TEST_SETTING_1_2_VALUE; $config->$sectionName[self::TEST_SETTING_1_3_NAME] = self::TEST_SETTING_1_3_VALUE; $config->$sectionName[self::TEST_SETTING_1_4_NAME] = self::TEST_SETTING_1_4_VALUE; $config->$sectionName[self::TEST_SETTING_1_5_NAME] = self::TEST_SETTING_1_5_VALUE; $config->$sectionName[self::TEST_SETTING_1_6_NAME] = self::TEST_SETTING_1_6_VALUE; $config->$sectionName[self::TEST_SETTING_1_7_NAME] = self::TEST_SETTING_1_7_VALUE; $config->$sectionName[self::TEST_SETTING_1_8_NAME] = self::TEST_SETTING_1_8_VALUE; // Add a second section so we are testing that we do not accidentally return it. $sectionName = self::TEST_SECTION_1_NAME . '_second_section'; // Add a setting with the same name as in section #1 but with a random int value. $config->$sectionName[self::TEST_SETTING_1_1_NAME] = random_int(PHP_INT_MIN, PHP_INT_MAX); // Add another setting to the same section with some bogus content. $config->$sectionName[self::TEST_SETTING_1_2_NAME . '_another'] = '127.0.0.1'; // Add the second section. // Add an array value like section=PluginsInstalled; setting=PluginsInstalled[]. $sectionName = self::TEST_SECTION_2_NAME; // Add some values to the setting array. $config->$sectionName[self::TEST_SETTING_2_1_NAME] = self::TEST_SETTING_2_1_VALUES; $config->$sectionName[self::TEST_SETTING_2_2_NAME] = self::TEST_SETTING_2_2_VALUES; $config->$sectionName[self::TEST_SETTING_2_3_NAME] = self::TEST_SETTING_2_3_VALUES; $config->$sectionName[self::TEST_SETTING_2_4_NAME] = self::TEST_SETTING_2_4_VALUES; $config->$sectionName[self::TEST_SETTING_2_5_NAME] = self::TEST_SETTING_2_5_VALUES; $config->$sectionName[self::TEST_SETTING_2_6_NAME] = self::TEST_SETTING_2_6_VALUES; $config->$sectionName[self::TEST_SETTING_2_7_NAME] = self::TEST_SETTING_2_7_VALUES; $config->forceSave(); return $config; } private static function removeTestConfigFile() { $configPath = self::getTestConfigFilePath(); if (file_exists($configPath)) { unlink($configPath); } } private static function makeNewConfig() { $settings = new GlobalSettingsProvider(null, self::getTestConfigFilePath()); return new Config($settings); } private function runCommandWithOptions(string $sectionName, string $settingName, string $value = ''): object { $inputArr = [ 'command' => self::COMMAND, '--section' => $sectionName, '--key' => $settingName, '-vvv' => false, ]; if (!empty($value)) { $inputArr['--value'] = $value; } $exitCode = $this->applicationTester->run($inputArr); // Pass true to getDisplay(true) to normalize line endings, then trim() bc CLI adds an \ automatically. $output = trim($this->applicationTester->getDisplay(true)); // Put the results in an easy-to-handle object format. return (object) ['exitCode' => $exitCode, 'output' => $output]; } private function runCommandWithArguments(string $sectionName, string $settingName = '', string $value = ''): object { $inputArr = [ 'command' => self::COMMAND, '-vvv' => false, 'argument' => $sectionName . '.' . $settingName . (empty($value) ? '' : ".$value"), ]; $exitCode = $this->applicationTester->run($inputArr); // Pass true to getDisplay(true) to normalize line endings, then trim() bc CLI adds an \ automatically. $output = trim($this->applicationTester->getDisplay(true)); // Put the results in an easy-to-handle object format. return (object) ['exitCode' => $exitCode, 'output' => $output]; } //************************************************************************* // Tests that should yield errors. //************************************************************************* public function testNoArgsShouldYieldError() { $inputArr = [ 'command' => 'config:get', '-vvv' => false, ]; $exitCode = $this->applicationTester->run($inputArr); // The CLI error code should be >0 indicating failure. $this->assertGreaterThan(0, $exitCode); // Pass true to getDisplay(true) to normalize line endings, then trim() bc CLI adds an \ automatically. $output = trim($this->applicationTester->getDisplay(true)); $this->assertStringContainsString('InvalidArgumentException', $output); } public function testEmptyArgsShouldYieldError() { // Pass empty section name. $resultObj = $this->runCommandWithArguments(''); // The CLI error code should be >0 indicating failure. $this->assertGreaterThan(0, $resultObj->exitCode); $this->assertStringContainsString('InvalidArgumentException', $resultObj->output); } public function testEmptyOptionsShouldYieldError() { // Pass empty section name. $resultObj = $this->runCommandWithOptions('', ''); // The CLI error code should be >0 indicating failure. $this->assertGreaterThan(0, $resultObj->exitCode); $this->assertStringContainsString('InvalidArgumentException', $resultObj->output); } public function testSetArgsAndOptionsShouldYieldError() { $inputArr = [ 'command' => 'config:get', 'argument' => self::TEST_SECTION_1_NAME . '.' . self::TEST_SETTING_1_1_NAME, '--section' => self::TEST_SECTION_1_NAME, '--key' => self::TEST_SETTING_1_1_NAME, '-vvv' => false, ]; $exitCode = $this->applicationTester->run($inputArr); // The CLI error code should be >0 indicating failure. $this->assertGreaterThan(0, $exitCode); // Pass true to getDisplay(true) to normalize line endings, then trim() bc CLI adds an \ automatically. $output = trim($this->applicationTester->getDisplay(true)); $this->assertStringContainsString('InvalidArgumentException', $output); } public function testEmptySectionShouldYieldError() { // Pass empty section name. $resultObj = $this->runCommandWithOptions('', self::TEST_SETTING_1_1_NAME); // The CLI error code should be >0 indicating failure. $this->assertGreaterThan(0, $resultObj->exitCode); $this->assertStringContainsString('InvalidArgumentException', $resultObj->output); } public function testScalarSettingWithArrayValShouldYieldError() { // Pass empty section name. $resultObj = $this->runCommandWithOptions(self::TEST_SECTION_1_NAME, self::TEST_SETTING_1_1_NAME, self::CLASS_NAME_SHORT . '_Array_key_does_not_exist'); // The CLI error code should be >0 indicating failure. $this->assertGreaterThan(0, $resultObj->exitCode); $this->assertStringContainsString('InvalidArgumentException', $resultObj->output); } public function testArrayWithNoValShouldYieldError() { // Pass empty section name. $resultObj = $this->runCommandWithOptions(self::TEST_SECTION_2_NAME, self::TEST_SETTING_2_1_NAME); // The CLI error code should be >0 indicating failure. $this->assertGreaterThan(0, $resultObj->exitCode); $this->assertStringContainsString('InvalidArgumentException', $resultObj->output); } //************************************************************************* // Tests for nonexistent data. //************************************************************************* public function testUsingOptsNonExistentSectionShouldYieldEmpty() { // Pass empty section name. $resultObj = $this->runCommandWithOptions(self::CLASS_NAME_SHORT . '_Section_does_not_exist', self::TEST_SETTING_1_1_NAME); // The CLI error code should be 0 indicating success. $this->assertEquals(0, $resultObj->exitCode, $this->getCommandDisplayOutputErrorMessage()); $expectedValue = self::MSG_NOTHING_FOUND; $this->assertEquals($expectedValue, $resultObj->output); } public function testUsingArgsNonExistentSectionShouldYieldEmpty() { // Pass empty section name. $resultObj = $this->runCommandWithArguments(self::CLASS_NAME_SHORT . '_Section_does_not_exist', self::TEST_SETTING_1_1_NAME); // The CLI error code should be 0 indicating success. $this->assertEquals(0, $resultObj->exitCode, $this->getCommandDisplayOutputErrorMessage()); $expectedValue = self::MSG_NOTHING_FOUND; $this->assertEquals($expectedValue, $resultObj->output); } public function testUsingOptsNonExistentSectionAndSettingShouldYieldEmpty() { // Pass empty section name. $resultObj = $this->runCommandWithOptions(self::CLASS_NAME_SHORT . '_Section_does_not_exist', self::CLASS_NAME_SHORT . '_Setting_does_not_exist'); // The CLI error code should be 0 indicating success. $this->assertEquals(0, $resultObj->exitCode, $this->getCommandDisplayOutputErrorMessage()); $expectedValue = self::MSG_NOTHING_FOUND; $this->assertEquals($expectedValue, $resultObj->output); } public function testUsingArgsNonExistentSectionAndSettingShouldYieldEmpty() { // Pass empty section name. $resultObj = $this->runCommandWithArguments(self::CLASS_NAME_SHORT . '_Section_does_not_exist', self::CLASS_NAME_SHORT . '_Setting_does_not_exist'); // The CLI error code should be 0 indicating success. $this->assertEquals(0, $resultObj->exitCode, $this->getCommandDisplayOutputErrorMessage()); $expectedValue = self::MSG_NOTHING_FOUND; $this->assertEquals($expectedValue, $resultObj->output); } public function testUsingOptsNonExistentSettingShouldYieldEmpty() { // Pass empty section name. $resultObj = $this->runCommandWithOptions(self::TEST_SECTION_1_NAME, self::CLASS_NAME_SHORT . '_Setting_does_not_exist'); // The CLI error code should be 0 indicating success. $this->assertEquals(0, $resultObj->exitCode, $this->getCommandDisplayOutputErrorMessage()); $expectedValue = self::MSG_NOTHING_FOUND; $this->assertEquals($expectedValue, $resultObj->output); } public function testUsingArgsNonExistentSettingShouldYieldEmpty() { // Pass empty section name. $resultObj = $this->runCommandWithArguments(self::TEST_SECTION_1_NAME, self::CLASS_NAME_SHORT . '_Setting_does_not_exist'); // The CLI error code should be 0 indicating success. $this->assertEquals(0, $resultObj->exitCode, $this->getCommandDisplayOutputErrorMessage()); $expectedValue = self::MSG_NOTHING_FOUND; $this->assertEquals($expectedValue, $resultObj->output); } public function testUsingOptsArrayWithInvalidValShouldYieldEmpty() { // Pass empty section name. $resultObj = $this->runCommandWithOptions(self::TEST_SECTION_2_NAME, self::TEST_SETTING_2_1_NAME, self::CLASS_NAME_SHORT . '_Array_key_does_not_exist'); // The CLI error code should be 0 indicating success. $this->assertEquals(0, $resultObj->exitCode, $this->getCommandDisplayOutputErrorMessage()); $expectedValue = self::MSG_NOTHING_FOUND; $this->assertEquals($expectedValue, $resultObj->output); } public function testUsingArgsArrayWithInvalidValShouldYieldEmpty() { // Pass empty section name. $resultObj = $this->runCommandWithArguments(self::TEST_SECTION_2_NAME, self::TEST_SETTING_2_1_NAME, self::CLASS_NAME_SHORT . '_Array_key_does_not_exist'); // The CLI error code should be 0 indicating success. $this->assertEquals(0, $resultObj->exitCode, $this->getCommandDisplayOutputErrorMessage()); $expectedValue = self::MSG_NOTHING_FOUND; $this->assertEquals($expectedValue, $resultObj->output); } //************************************************************************* // Tests for existing data. //************************************************************************* /** * @dataProvider getSingleSettingDataProvider1 */ public function testUsingOptsDeleteSingleSetting($sectionName, $settingName, $settingValue) { $resultObj = $this->runCommandWithOptions($sectionName, $settingName); // The CLI error code should be 0 indicating success. $this->assertEquals(0, $resultObj->exitCode, $this->getCommandDisplayOutputErrorMessage()); $this->assertStringContainsString('Success:', $resultObj->output); $config = $this->makeNewConfig(); $configDump = $config->dumpConfig(); $needle = $settingName . ' = ' . $settingValue; $this->assertStringNotContainsString($needle, $configDump); } /** * @dataProvider getSingleSettingDataProvider2 */ public function testUsingArgsDeleteSingleSetting($sectionName, $settingName, $settingValue) { $resultObj = $this->runCommandWithArguments($sectionName, $settingName); // The CLI error code should be 0 indicating success. $this->assertEquals(0, $resultObj->exitCode, $this->getCommandDisplayOutputErrorMessage()); $this->assertStringContainsString('Success:', $resultObj->output); $config = $this->makeNewConfig(); $configDump = $config->dumpConfig(); $needle = $settingName . ' = ' . $settingValue; $this->assertStringNotContainsString($needle, $configDump); } /** * @dataProvider getArraySettingDataProvider1 */ public function testUsingOptsDeleteArraySetting($sectionName, $settingName, $settingValue) { $resultObj = $this->runCommandWithOptions($sectionName, $settingName, $settingValue); // The CLI error code should be 0 indicating success. $this->assertEquals(0, $resultObj->exitCode, $this->getCommandDisplayOutputErrorMessage()); $this->assertStringContainsString('Success:', $resultObj->output); $config = $this->makeNewConfig(); $configDump = $config->dumpConfig(); $needle = $settingName . ' = ' . $settingValue; $this->assertStringNotContainsString($needle, $configDump); } /** * @dataProvider getArraySettingDataProvider2 */ public function testUsingArgsDeleteArraySetting($sectionName, $settingName, $settingValue) { $resultObj = $this->runCommandWithArguments($sectionName, $settingName, $settingValue); // The CLI error code should be 0 indicating success. $this->assertEquals(0, $resultObj->exitCode, $this->getCommandDisplayOutputErrorMessage()); $this->assertStringContainsString('Success:', $resultObj->output); $config = $this->makeNewConfig(); $configDump = $config->dumpConfig(); $needle = $settingName . ' = ' . $settingValue; $this->assertStringNotContainsString($needle, $configDump); } public function getSingleSettingDataProvider1() { yield 'Section 1, Setting 1.1' => [self::TEST_SECTION_1_NAME, self::TEST_SETTING_1_1_NAME, self::TEST_SETTING_1_1_VALUE]; yield 'Section 1, Setting 1.2' => [self::TEST_SECTION_1_NAME, self::TEST_SETTING_1_2_NAME, self::TEST_SETTING_1_2_VALUE]; yield 'Section 1, Setting 1.3 - IPv4 address with port' => [self::TEST_SECTION_1_NAME, self::TEST_SETTING_1_3_NAME, self::TEST_SETTING_1_3_VALUE]; yield 'Section 1, Setting 1.4 - IPv6 address with port' => [self::TEST_SECTION_1_NAME, self::TEST_SETTING_1_4_NAME, self::TEST_SETTING_1_4_VALUE]; } public function getSingleSettingDataProvider2() { yield 'Section 1, Setting 1.5 - IPv4 subnet' => [self::TEST_SECTION_1_NAME, self::TEST_SETTING_1_5_NAME, self::TEST_SETTING_1_5_VALUE]; yield 'Section 1, Setting 1.6 - IPv6 subnet' => [self::TEST_SECTION_1_NAME, self::TEST_SETTING_1_6_NAME, self::TEST_SETTING_1_6_VALUE]; yield 'Section 1, Setting 1.7 - mail address with extension' => [self::TEST_SECTION_1_NAME, self::TEST_SETTING_1_7_NAME, self::TEST_SETTING_1_7_VALUE]; yield 'Section 1, Setting 1.8 - comma separated list' => [self::TEST_SECTION_1_NAME, self::TEST_SETTING_1_8_NAME, self::TEST_SETTING_1_8_VALUE]; } public function getArraySettingDataProvider1() { yield 'Section 2, Setting 2.1' => [self::TEST_SECTION_2_NAME, self::TEST_SETTING_2_1_NAME, self::TEST_SETTING_2_1_VALUE_0]; yield 'Section 2, Setting 2.2 - IPv4 address with port' => [self::TEST_SECTION_2_NAME, self::TEST_SETTING_2_2_NAME, self::TEST_SETTING_2_2_VALUE_0]; yield 'Section 2, Setting 2.3 - IPv6 address with port' => [self::TEST_SECTION_2_NAME, self::TEST_SETTING_2_3_NAME, self::TEST_SETTING_2_3_VALUE_0]; yield 'Section 2, Setting 2.4 - IPv4 subnet' => [self::TEST_SECTION_2_NAME, self::TEST_SETTING_2_4_NAME, self::TEST_SETTING_2_4_VALUE_0]; yield 'Section 2, Setting 2.5 - IPv6 subnet' => [self::TEST_SECTION_2_NAME, self::TEST_SETTING_2_5_NAME, self::TEST_SETTING_2_5_VALUE_0]; yield 'Section 2, Setting 2.6 - mail address with extension' => [self::TEST_SECTION_2_NAME, self::TEST_SETTING_2_6_NAME, self::TEST_SETTING_2_6_VALUE_0]; yield 'Section 2, Setting 2.7 - comma separated list' => [self::TEST_SECTION_2_NAME, self::TEST_SETTING_2_7_NAME, self::TEST_SETTING_2_7_VALUE_0]; } public function getArraySettingDataProvider2() { yield 'Section 2, Setting 2.1' => [self::TEST_SECTION_2_NAME, self::TEST_SETTING_2_1_NAME, self::TEST_SETTING_2_1_VALUE_1]; yield 'Section 2, Setting 2.2 - IPv4 address with port' => [self::TEST_SECTION_2_NAME, self::TEST_SETTING_2_2_NAME, self::TEST_SETTING_2_2_VALUE_1]; yield 'Section 2, Setting 2.3 - IPv6 address with port' => [self::TEST_SECTION_2_NAME, self::TEST_SETTING_2_3_NAME, self::TEST_SETTING_2_3_VALUE_1]; yield 'Section 2, Setting 2.4 - IPv4 subnet' => [self::TEST_SECTION_2_NAME, self::TEST_SETTING_2_4_NAME, self::TEST_SETTING_2_4_VALUE_1]; yield 'Section 2, Setting 2.5 - IPv6 subnet' => [self::TEST_SECTION_2_NAME, self::TEST_SETTING_2_5_NAME, self::TEST_SETTING_2_5_VALUE_1]; yield 'Section 2, Setting 2.6 - mail address with extension' => [self::TEST_SECTION_2_NAME, self::TEST_SETTING_2_6_NAME, self::TEST_SETTING_2_6_VALUE_1]; yield 'Section 2, Setting 2.7 - comma separated list' => [self::TEST_SECTION_2_NAME, self::TEST_SETTING_2_7_NAME, self::TEST_SETTING_2_7_VALUE_1]; } }