config_preview_deploy-1.0.0-alpha3/tests/src/Kernel/LargeDiffHandlingTest.php
tests/src/Kernel/LargeDiffHandlingTest.php
<?php
declare(strict_types=1);
namespace Drupal\Tests\config_preview_deploy\Kernel;
use Drupal\Component\Serialization\Yaml;
use Drupal\config_preview_deploy\ProductionConfigDeployer;
use Drupal\config_preview_deploy\ConfigDiff;
use Drupal\KernelTests\KernelTestBase;
use SebastianBergmann\Diff\Differ;
use SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder;
/**
* Tests handling of large configuration diffs.
*
* Verifies that the module can handle complex scenarios with many
* configuration files and large diffs without performance issues.
*
* @group config_preview_deploy
*/
class LargeDiffHandlingTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = [
'config_preview_deploy',
'system',
'user',
'field',
'node',
'text',
'views',
];
/**
* The production config deployer service.
*/
protected ProductionConfigDeployer $productionConfigDeployer;
/**
* The config diff service.
*/
protected ConfigDiff $configDiff;
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
$this->installEntitySchema('user');
$this->installEntitySchema('node');
$this->installConfig(['system', 'user', 'field', 'node', 'text', 'views']);
$this->productionConfigDeployer = $this->container->get('config_preview_deploy.production_config_deployer');
$this->configDiff = $this->container->get('config_preview_deploy.config_diff');
// Fail tests if patch tool is not available.
$patchTool = $this->container->get('config_preview_deploy.patch_tool');
if (!$patchTool->isAvailable()) {
$this->fail('GNU patch tool is required for large diff tests. Install with: apt install patch');
}
}
/**
* Tests handling of multiple configuration file changes in a single diff.
*/
public function testMultipleConfigurationFileChanges(): void {
$activeStorage = $this->container->get('config.storage');
// Create a diff that modifies multiple configuration files.
$configs = [
'system.site' => [
'original' => $activeStorage->read('system.site'),
'changes' => ['name' => 'Large Diff Test Site', 'slogan' => 'Testing multiple configs'],
],
'system.performance' => [
'original' => $activeStorage->read('system.performance'),
'changes' => ['test_field' => 'Large diff test value'],
],
];
$fullDiff = '';
foreach ($configs as $configName => $configData) {
$originalYaml = Yaml::encode($configData['original']);
$modifiedConfig = $configData['original'];
foreach ($configData['changes'] as $key => $value) {
$modifiedConfig[$key] = $value;
}
$modifiedYaml = Yaml::encode($modifiedConfig);
$outputBuilder = new UnifiedDiffOutputBuilder(
"--- a/$configName.yml\n+++ b/$configName.yml\n",
TRUE
);
$differ = new Differ($outputBuilder);
$fullDiff .= $differ->diff($originalYaml, $modifiedYaml);
}
// Test validation of multi-file diff.
$validation = $this->configDiff->validateDiff($fullDiff);
$this->assertTrue($validation['valid'], 'Multi-file diff should be valid');
$this->assertEquals(2, $validation['config_count'], 'Should detect 2 configuration changes');
// Test applying multi-file diff.
$results = $this->configDiff->validateAndApplyDiff($fullDiff);
$this->assertCount(2, $results, 'Should have applied changes to 2 configurations');
$this->assertArrayHasKey('system.site', $results, 'Should have updated system.site');
$this->assertArrayHasKey('system.performance', $results, 'Should have updated system.performance');
// Verify changes were applied correctly.
$updatedSite = $activeStorage->read('system.site');
$this->assertEquals('Large Diff Test Site', $updatedSite['name'], 'Site name should be updated');
$this->assertEquals('Testing multiple configs', $updatedSite['slogan'], 'Slogan should be updated');
$updatedPerformance = $activeStorage->read('system.performance');
$this->assertEquals('Large diff test value', $updatedPerformance['test_field'], 'Test field should be updated');
}
/**
* Tests handling of configuration with large amounts of data.
*/
public function testLargeConfigurationData(): void {
$activeStorage = $this->container->get('config.storage');
// Create a configuration with a large amount of data.
$largeConfig = $activeStorage->read('system.site');
// Add many fields to simulate a large configuration.
for ($i = 0; $i < 100; $i++) {
$largeConfig["large_field_$i"] = str_repeat("Large data content for field $i. ", 50);
}
$originalYaml = Yaml::encode($activeStorage->read('system.site'));
$modifiedYaml = Yaml::encode($largeConfig);
// Generate diff for large configuration.
$outputBuilder = new UnifiedDiffOutputBuilder(
"--- a/system.site.yml\n+++ b/system.site.yml\n",
TRUE
);
$differ = new Differ($outputBuilder);
$largeDiff = $differ->diff($originalYaml, $modifiedYaml);
// Verify the diff is substantial.
$this->assertGreaterThan(10000, strlen($largeDiff), 'Diff should be large (>10KB)');
// Test validation of large diff.
$validation = $this->configDiff->validateDiff($largeDiff);
$this->assertTrue($validation['valid'], 'Large diff should be valid');
$this->assertGreaterThan(0, $validation['config_count'], 'Should detect configuration changes');
// Test applying large diff.
$results = $this->configDiff->validateAndApplyDiff($largeDiff);
$this->assertArrayHasKey('system.site', $results, 'Should have updated system.site');
// Verify some of the large data was applied.
$updatedConfig = $activeStorage->read('system.site');
$this->assertArrayHasKey('large_field_0', $updatedConfig, 'First large field should exist');
$this->assertArrayHasKey('large_field_99', $updatedConfig, 'Last large field should exist');
$this->assertStringContainsString('Large data content for field 0', $updatedConfig['large_field_0'], 'Field content should be correct');
}
/**
* Tests handling of configuration files with complex nested structures.
*/
public function testComplexNestedConfigurationChanges(): void {
$activeStorage = $this->container->get('config.storage');
// Use system.site for complex nested structure changes.
$originalConfig = $activeStorage->read('system.site');
$complexConfig = $originalConfig;
// Add complex nested structure.
$complexConfig['complex_structure'] = [
'level1' => [
'level2' => [
'level3' => [
'deeply_nested_field' => 'Deep value',
'array_field' => ['item1', 'item2', 'item3'],
'numeric_field' => 12345,
'boolean_field' => TRUE,
],
'level3_alternative' => [
'alternative_data' => 'Alternative value',
],
],
'level2_sibling' => [
'sibling_data' => 'Sibling value',
],
],
'level1_alternative' => [
'alternative_structure' => [
'alt_field' => 'Alt value',
],
],
];
$originalYaml = Yaml::encode($originalConfig);
$modifiedYaml = Yaml::encode($complexConfig);
// Generate diff for complex nested structure.
$outputBuilder = new UnifiedDiffOutputBuilder(
"--- a/system.site.yml\n+++ b/system.site.yml\n",
TRUE
);
$differ = new Differ($outputBuilder);
$complexDiff = $differ->diff($originalYaml, $modifiedYaml);
// Test validation of complex diff.
$validation = $this->configDiff->validateDiff($complexDiff);
$this->assertTrue($validation['valid'], 'Complex nested diff should be valid');
// Test applying complex diff.
$results = $this->configDiff->validateAndApplyDiff($complexDiff);
$this->assertArrayHasKey('system.site', $results, 'Should have updated system.site');
// Verify complex nested structure was applied correctly.
$updatedConfig = $activeStorage->read('system.site');
$this->assertArrayHasKey('complex_structure', $updatedConfig, 'Complex structure should exist');
$this->assertEquals('Deep value', $updatedConfig['complex_structure']['level1']['level2']['level3']['deeply_nested_field'], 'Deeply nested field should be correct');
$this->assertEquals(['item1', 'item2', 'item3'], $updatedConfig['complex_structure']['level1']['level2']['level3']['array_field'], 'Array field should be correct');
$this->assertTrue($updatedConfig['complex_structure']['level1']['level2']['level3']['boolean_field'], 'Boolean field should be correct');
}
/**
* Tests performance with diff validation and application.
*/
public function testDiffProcessingPerformance(): void {
$activeStorage = $this->container->get('config.storage');
// Create a moderately complex diff (simulating real-world usage).
$configs = [];
$configNames = ['system.site', 'system.performance'];
foreach ($configNames as $configName) {
$originalConfig = $activeStorage->read($configName);
$modifiedConfig = $originalConfig;
// Add several fields to each config.
for ($i = 0; $i < 20; $i++) {
$modifiedConfig["performance_test_field_$i"] = "Performance test value $i";
}
$configs[$configName] = [
'original' => $originalConfig,
'modified' => $modifiedConfig,
];
}
// Generate combined diff.
$fullDiff = '';
foreach ($configs as $configName => $configData) {
$originalYaml = Yaml::encode($configData['original']);
$modifiedYaml = Yaml::encode($configData['modified']);
$outputBuilder = new UnifiedDiffOutputBuilder(
"--- a/$configName.yml\n+++ b/$configName.yml\n",
TRUE
);
$differ = new Differ($outputBuilder);
$fullDiff .= $differ->diff($originalYaml, $modifiedYaml);
}
// Measure validation performance.
$startTime = microtime(TRUE);
$validation = $this->configDiff->validateDiff($fullDiff);
$validationTime = microtime(TRUE) - $startTime;
$this->assertTrue($validation['valid'], 'Performance test diff should be valid');
$this->assertLessThan(5.0, $validationTime, 'Validation should complete within 5 seconds');
// Measure application performance.
$startTime = microtime(TRUE);
$results = $this->configDiff->validateAndApplyDiff($fullDiff);
$applicationTime = microtime(TRUE) - $startTime;
$this->assertCount(2, $results, 'Should have applied changes to 2 configurations');
$this->assertLessThan(10.0, $applicationTime, 'Application should complete within 10 seconds');
}
}
