Verified Commit fdf0228f authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3352851 by catch, Fabianx, mondrake, xjm, alexpott: Allow assertions on...

Issue #3352851 by catch, Fabianx, mondrake, xjm, alexpott: Allow assertions on the number of database queries run during tests

(cherry picked from commit b1a87360)
parent a6554fca
Loading
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -2205,7 +2205,9 @@ public static function removeDatabaseEntriesFromDebugBacktrace(array $backtrace,
   *   The debug backtrace.
   */
  protected function getDebugBacktrace(): array {
    return debug_backtrace();
    // @todo: allow a backtrace including all arguments as an option.
    // See https://www.drupal.org/project/drupal/issues/3401906
    return debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
  }

}
+5 −0
Original line number Diff line number Diff line
name: 'Performance test'
type: module
description: 'Supports performance testing with PerformanceTestTrait'
package: Testing
version: VERSION
+9 −0
Original line number Diff line number Diff line
services:
  Drupal\performance_test\PerformanceDataCollector:
    tags:
      - { name: event_subscriber }
      - { name: needs_destruction, priority: -1000 }
  Drupal\performance_test\DatabaseEventEnabler:
    arguments: ['@database']
    tags:
      - { name: http_middleware, priority: 1000, responder: true }
+32 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\performance_test;

use Drupal\Core\Database\Connection;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Drupal\Core\Database\Event\StatementExecutionEndEvent;
use Drupal\Core\Database\Event\StatementExecutionStartEvent;

class DatabaseEventEnabler implements HttpKernelInterface {

  public function __construct(protected readonly HttpKernelInterface $httpKernel, protected readonly Connection $connection) {}

  /**
   * {@inheritdoc}
   */
  public function handle(Request $request, $type = self::MAIN_REQUEST, $catch = TRUE): Response {
    if ($type === static::MAIN_REQUEST) {
      $this->connection->enableEvents([
        // StatementExecutionStartEvent must be enabled in order for
        // StatementExecutionEndEvent to be fired, even though we only subscribe
        // to the latter event.
        StatementExecutionStartEvent::class,
        StatementExecutionEndEvent::class,
      ]);
    }
    return $this->httpKernel->handle($request, $type, $catch);
  }

}
+51 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\performance_test;

use Drupal\Core\Database\Event\StatementExecutionEndEvent;
use Drupal\Core\DestructableInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class PerformanceDataCollector implements EventSubscriberInterface, DestructableInterface {

  /**
   * Database events collected during the request.
   *
   * @var Drupal\Core\Database\Event\StatementExecutionEndEvent[]
   */
  protected array $databaseEvents = [];

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    return [
      StatementExecutionEndEvent::class => 'onStatementExecutionEnd',
    ];
  }

  /**
   * Logs database statements.
   */
  public function onStatementExecutionEnd(StatementExecutionEndEvent $event): void {
    // Use the event object as a value object.
    $this->databaseEvents[] = $event;
  }

  /**
   * {@inheritdoc}
   */
  public function destruct(): void {
    // Get the events now before issuing any more database queries so that this
    // logging does not become part of the recorded data.
    $database_events = $this->databaseEvents;

    // Deliberately do not use an injected key value service to avoid any
    // overhead up until this point.
    $collection = \Drupal::keyValue('performance_test');
    $existing_data = $collection->get('performance_test_data') ?? ['database_events' => []];
    $existing_data['database_events'] = array_merge($existing_data['database_events'], $database_events);
    $collection->set('performance_test_data', $existing_data);
  }

}
Loading