Commit 678a9a06 authored by Takumaru Sekine's avatar Takumaru Sekine Committed by Yas Naoi
Browse files

Issue #3324005 by sekinet, yas: Add test cases for OpenStack port (CRUD)

parent 2f070310
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -55,7 +55,7 @@ class OpenStackPortEditForm extends AwsCloudContentForm {
  protected $openStackOperationsService;

  /**
   * OpenStackPortCreateForm constructor.
   * OpenStackPortEditForm constructor.
   *
   * @param \Drupal\aws_cloud\Service\AwsCloud\AwsCloudOperationsServiceInterface $aws_cloud_operations_service
   *   The AWS Cloud Operations service.
+39 −0
Original line number Diff line number Diff line
@@ -718,6 +718,45 @@ class OpenStackServiceMock extends OpenStackService {
    return $this->getMockData(__FUNCTION__);
  }

  /**
   * Create an OpenStack port.
   *
   * @param array $params
   *   Parameters to pass to the API.
   *
   * @return array
   *   The port create API response.
   */
  public function createPort(array $params = []): array {
    return $this->getMockData(__FUNCTION__);
  }

  /**
   * Update an OpenStack port.
   *
   * @param array $params
   *   Parameters to pass to the API.
   *
   * @return array
   *   The port update API response.
   */
  public function updatePort(array $params = []): array {
    return $this->getMockData(__FUNCTION__);
  }

  /**
   * Delete an OpenStack port.
   *
   * @param array $params
   *   Parameters to pass to the API.
   *
   * @return array
   *   The port delete API response.
   */
  public function deletePort(array $params = []): array {
    return $this->getMockData(__FUNCTION__);
  }

  /**
   * Get routers.
   *
+440 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\Tests\openstack\Functional\OpenStack;

use Drupal\openstack\Entity\OpenStackNetwork;
use Drupal\openstack\Entity\OpenStackPort;
use Drupal\openstack\Entity\OpenStackSubnet;
use Drupal\Tests\openstack\Functional\OpenStackTestBase;

/**
 * Tests OpenStack port.
 *
 * @group OpenStack
 */
class OpenStackPortTest extends OpenStackTestBase {

  public const OPENSTACK_PORT_REPEAT_COUNT = 2;

  /**
   * {@inheritdoc}
   */
  protected function getPermissions(): array {
    return [
      'view all cloud service providers',
      'list openstack port',
      'add openstack port',
      'view any openstack port',
      'edit any openstack port',
      'delete any openstack port',
    ];
  }

  /**
   * {@inheritdoc}
   *
   * @throws \Exception
   */
  protected function getMockDataTemplateVars(): array {
    return [
      'port_id' => 'port-' . $this->getRandomId(),
      'network_id' => 'network-' . $this->getRandomId(),
      'project_id' => $this->cloudConfig->get('field_project_id')->value,
      'create_time' => date('c'),
    ];
  }

  /**
   * Tests CRUD for port information.
   *
   * @throws \Behat\Mink\Exception\ExpectationException
   * @throws \Exception
   */
  public function testPort(): void {
    $cloud_context = $this->cloudContext;

    // List port for OpenStack.
    $this->drupalGet("/clouds/openstack/$cloud_context/port");
    $this->assertNoErrorMessage();

    // Create random networks.
    $networks = $this->createNetworksRandomTestFormData();
    $this->updateDescribeNetworksMockData($networks);

    // Create the network entities.
    $i = 1;
    foreach ($networks ?: [] as $network) {
      $this->createNetworkTestEntity(OpenStackNetwork::class, $i++, $cloud_context, $network['Name'], $network['NetworkId']);

      // Create random subnets.
      $subnets = $this->createopenstackSubnetsRandomTestFormData();
      $this->updateDescribeSubnetsMockData($subnets);
      $subnet_index = 1;
      foreach ($subnets ?: [] as $subnet) {
        $this->createOpenStackSubnetTestEntity(OpenStackSubnet::class, $subnet_index++, $cloud_context, $subnet['Name'], $subnet['SubnetId'], $network['NetworkId']);

        $subnet_index++;
      }

      $i++;
    }

    // Add a new port.
    $add = $this->createPortTestFormData(self::OPENSTACK_PORT_REPEAT_COUNT);

    for ($i = 0, $num = 1; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++, $num++) {
      $this->addPortMockData($add[$i], $cloud_context, $this->webUser->id());

      // Set network ID.
      $add[$i]['network_id'] = $networks[array_rand($networks)]['NetworkId'];
      // Set subnet ID.
      $add[$i]['subnet'] = $subnets[array_rand($subnets)]['SubnetId'];

      $this->drupalGet("/clouds/openstack/$cloud_context/port/add");
      $this->submitForm(
        $add[$i],
        $this->t('Save'));

      $this->assertNoErrorMessage();
      $t_args = ['@type' => 'Port', '%label' => $add[$i]['name']];
      $this->assertSession()->pageTextContains(strip_tags($this->t('The @type %label has been created.', $t_args)));

      // Make sure View.
      $this->drupalGet("/clouds/openstack/$cloud_context/port/$num");
      $this->assertNoErrorMessage();

      // Make sure listing.
      $this->drupalGet("/clouds/openstack/$cloud_context/port");
      $this->assertNoErrorMessage();

      for ($j = 0; $j < $num; $j++) {
        $this->assertSession()->pageTextContains($add[$j]['name']);
      }

      // Make sure uid.
      $this->drupalGet("/clouds/openstack/$cloud_context/port/$num");
      $this->assertSession()->pageTextContains($this->webUser->getAccountName());
    }

    for ($i = 0, $num = 1; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++, $num++) {
      // Make sure the all port listing exists.
      $this->drupalGet('/clouds/openstack/port');
      $this->assertNoErrorMessage();

      for ($j = 0; $j < $num; $j++) {
        $this->assertSession()->pageTextContains($add[$j]['name']);
      }
    }

    // Edit port information.
    $edit = $this->createPortTestFormData(self::OPENSTACK_PORT_REPEAT_COUNT);
    for ($i = 0, $num = 1; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++, $num++) {
      unset(
        $edit[$i]['network_id'],
        $edit[$i]['subnet'],
        $edit[$i]['fixed_ips'],
        $edit[$i]['device_id'],
        $edit[$i]['device_owner'],
        $edit[$i]['ip_address_or_subnet'],
      );
      $this->updatePortMockData($i, $edit[$i]['name']);
      $this->drupalGet("/clouds/openstack/$cloud_context/port/$num/edit");

      $this->submitForm(
        $edit[$i],
        $this->t('Save'));
      $this->assertNoErrorMessage();
      $t_args = ['@type' => 'Port', '%label' => $edit[$i]['name']];
      $this->assertSession()->pageTextContains(strip_tags($this->t('The @type %label has been updated.', $t_args)));

      $this->drupalGet("/clouds/openstack/$cloud_context/port");
      $this->assertNoErrorMessage();

      $this->assertSession()->pageTextContains($edit[$i]['name']);

      // Make sure listing.
      $this->drupalGet("/clouds/openstack/$cloud_context/port");
      $this->assertNoErrorMessage();

      for ($j = 0; $j < $num; $j++) {
        $this->assertSession()->pageTextContains($edit[$i]['name']);
      }

      // Make sure uid.
      $this->drupalGet("/clouds/openstack/$cloud_context/port/$num");
      $this->assertSession()->pageTextContains($this->webUser->getAccountName());
    }

    // Delete port.
    for ($i = 0, $num = 1; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++, $num++) {
      $this->drupalGet("/clouds/openstack/$cloud_context/port/$num/delete");
      $this->assertNoErrorMessage();
      $this->drupalGet("/clouds/openstack/$cloud_context/port/$num/delete");
      $this->submitForm(
        [],
        $this->t('Delete'));

      $this->assertNoErrorMessage();
      $t_args = ['@type' => 'Port', '@label' => $edit[$i]['name']];
      $this->assertSession()->pageTextContains(strip_tags($this->t('The @type @label has been deleted.', $t_args)));

      // Make sure listing.
      $this->drupalGet("/clouds/openstack/$cloud_context/port");
      $this->assertNoErrorMessage();
    }
  }

  /**
   * Tests deleting ports with bulk operation.
   *
   * @throws \Exception
   */
  public function testPortBulk(): void {
    for ($i = 0; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++) {
      // Create port.
      $ports = $this->createPortsRandomTestFormData();
      $index = 0;
      $entities = [];
      foreach ($ports ?: [] as $port) {
        $entities[] = $this->createPortTestEntity(OpenStackPort::class, $index++, $this->cloudContext, $port['Name']);
      }

      // The first parameter type should be 'port' in OpenStack.
      $this->runTestEntityBulk('port', $entities);
    }
  }

  /**
   * Test updating port.
   *
   * @throws \Behat\Mink\Exception\ExpectationException
   */
  public function testUpdatePortList(): void {
    $cloud_context = $this->cloudContext;

    // Add a new port.
    $add = $this->createPortTestFormData(self::OPENSTACK_PORT_REPEAT_COUNT);
    for ($i = 0; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++) {
      $this->reloadMockData();

      $this->addPortMockData($add[$i], $cloud_context, $this->webUser->id());
    }

    // Make sure listing.
    $this->drupalGet("/clouds/openstack/$cloud_context/port");
    $this->assertNoErrorMessage();
    for ($i = 0; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++) {
      $this->assertSession()->pageTextNotContains($add[$i]['name']);
    }

    // Click 'Refresh'.
    $this->clickLink($this->t('Refresh'));
    $this->assertSession()->pageTextContains($this->t('Updated ports.'));
    // Make sure listing.
    for ($i = 0; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++) {
      $this->assertSession()->pageTextContains($add[$i]['name']);
    }

    // Make sure detailed and edit view.
    for ($i = 0, $num = 1; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++, $num++) {

      // Confirm the detailed view.
      $this->drupalGet("/clouds/openstack/$cloud_context/port/$num");
      $this->assertSession()->linkExists($this->t('Edit'));
      $this->assertSession()->linkByHrefExists("/clouds/openstack/$cloud_context/port/$num/edit");
      $this->assertSession()->linkExists($this->t('Delete'));
      $this->assertSession()->linkByHrefExists("/clouds/openstack/$cloud_context/port/$num/delete");
      $this->assertSession()->linkExists($this->t('List OpenStack ports'));
      // Make sure uid.
      $this->assertSession()->pageTextContains($this->webUser->getAccountName());
      // Click 'Refresh'.
      $this->clickLink($this->t('List OpenStack ports'));
      $this->assertNoErrorMessage();
    }

    // Edit port information.
    for ($i = 0; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++, $num++) {

      // Change port name in mock data.
      $add[$i]['name'] = 'eni-' . $this->getRandomId();
      $this->updatePortMockData($i, $add[$i]['name']);

    }

    // Make sure listing.
    $this->drupalGet("/clouds/openstack/$cloud_context/port");
    $this->assertNoErrorMessage();
    for ($i = 0; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++) {
      $this->assertSession()->pageTextNotContains($add[$i]['name']);
    }

    // Click 'Refresh'.
    $this->clickLink($this->t('Refresh'));
    $this->assertSession()->pageTextContains($this->t('Updated ports.'));
    // Make sure listing.
    for ($i = 0; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++) {
      $this->assertSession()->pageTextContains($add[$i]['name']);
    }

    // Delete port in mock data.
    for ($i = 0; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++) {
      $this->deleteFirstPortMockData();
    }

    // Make sure listing.
    $this->drupalGet("/clouds/openstack/$cloud_context/port");
    $this->assertNoErrorMessage();
    for ($i = 0; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++) {
      $this->assertSession()->pageTextContains($add[$i]['name']);
    }

    // Click 'Refresh'.
    $this->clickLink($this->t('Refresh'));
    $this->assertSession()->pageTextContains($this->t('Updated ports.'));
    // Make sure listing.
    for ($i = 0; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++) {
      $this->assertSession()->pageTextNotContains($add[$i]['name']);
    }

  }

  /**
   * Test updating all ports.
   *
   * @throws \Behat\Mink\Exception\ExpectationException
   * @throws \Exception
   */
  public function testUpdateAllPortList(): void {
    $cloud_configs = [];

    // List port for OpenStack.
    $this->drupalGet('/clouds/openstack/port');
    $this->assertNoErrorMessage();

    // Create Cloud Config.
    for ($i = 0; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++) {
      $this->cloudContext = $this->random->name(8);
      $cloud_config = $this->createCloudConfigTestEntity($this->cloudContext, $this->cloudConfig->get('field_use_openstack_ec2_api')->value);
      $cloud_configs[] = $cloud_config;
    }

    // Add a new port.
    foreach ($cloud_configs ?: [] as $cloud_config) {
      $cloud_context = $cloud_config->getCloudContext();
      $add = $this->createPortTestFormData(self::OPENSTACK_PORT_REPEAT_COUNT);
      for ($i = 0; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++) {
        $this->reloadMockData();

        $this->addPortMockData($add[$i], $cloud_context, $this->webUser->id());
      }
    }

    // Make sure listing.
    $this->drupalGet('/clouds/openstack/port');
    $this->assertNoErrorMessage();
    for ($i = 0; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++) {
      $this->assertSession()->pageTextNotContains($add[$i]['name']);
    }

    // Click 'Refresh'.
    $this->clickLink($this->t('Refresh'));
    foreach ($cloud_configs ?: [] as $cloud_config) {
      $this->assertSession()->pageTextContains($this->t('Updated @resources of @cloud_config cloud service provider.', [
        '@resources' => 'Ports',
        '@cloud_config' => $cloud_config->getName(),
      ]));
    }

    // Make sure listing.
    for ($i = 0; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++) {
      $this->assertSession()->pageTextContains($add[$i]['name']);
    }

    // Make sure detailed and edit view.
    foreach ($cloud_configs ?: [] as $cloud_config) {
      $cloud_context = $cloud_config->getCloudContext();
      for ($i = 0, $num = 1; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++, $num++) {

        // Confirm the detailed view.
        $this->drupalGet("/clouds/openstack/${cloud_context}/port/${num}");
        $this->assertSession()->linkExists($this->t('Edit'));
        $this->assertSession()->linkByHrefExists("/clouds/openstack/${cloud_context}/port/${num}/edit");
        $this->assertSession()->linkExists($this->t('Delete'));
        $this->assertSession()->linkByHrefExists("/clouds/openstack/${cloud_context}/port/${num}/delete");
        $this->assertSession()->linkExists($this->t('List OpenStack ports'));
        // Click 'List OpenStack ports'.
        $this->clickLink($this->t('List OpenStack ports'));
        $this->assertNoErrorMessage();
      }
    }

    // Edit Port information.
    foreach ($cloud_configs ?: [] as $cloud_config) {
      for ($i = 0; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++, $num++) {
        // Change port name in mock data.
        $add[$i]['name'] = "eni-{$this->getRandomId()}";
        $this->updatePortMockData($i, $add[$i]['name']);
      }
    }

    // Make sure listing.
    $this->drupalGet('/clouds/openstack/port');
    $this->assertNoErrorMessage();
    for ($i = 0; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++) {
      $this->assertSession()->pageTextNotContains($add[$i]['name']);
    }

    // Click 'Refresh'.
    $this->clickLink($this->t('Refresh'));
    foreach ($cloud_configs ?: [] as $cloud_config) {
      $this->assertSession()->pageTextContains($this->t('Updated @resources of @cloud_config cloud service provider.', [
        '@resources' => 'Ports',
        '@cloud_config' => $cloud_config->getName(),
      ]));
    }

    // Make sure listing.
    for ($i = 0; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++) {
      $this->assertSession()->pageTextContains($add[$i]['name']);
    }

    // Delete port in mock data.
    for ($i = 0; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++) {
      $this->deleteFirstPortMockData();
    }

    // Make sure listing.
    $this->drupalGet('/clouds/openstack/port');
    $this->assertNoErrorMessage();
    for ($i = 0; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++) {
      $this->assertSession()->pageTextContains($add[$i]['name']);
    }

    // Click 'Refresh'.
    $this->clickLink($this->t('Refresh'));
    foreach ($cloud_configs ?: [] as $cloud_config) {
      $this->assertSession()->pageTextContains($this->t('Updated @resources of @cloud_config cloud service provider.', [
        '@resources' => 'Ports',
        '@cloud_config' => $cloud_config->getName(),
      ]));
    }

    // Make sure listing.
    for ($i = 0; $i < self::OPENSTACK_PORT_REPEAT_COUNT; $i++) {
      $this->assertSession()->pageTextNotContains($add[$i]['name']);
    }

  }

  /**
   * Check if service type is EC2 or REST.
   *
   * @return bool
   *   TRUE if cloud config type is EC2 API, otherwise FALSE.
   */
  protected function getEc2ServiceType(): bool {
    // OpenStack Port uses REST only.
    return FALSE;
  }

}
+96 −6
Original line number Diff line number Diff line
@@ -255,9 +255,9 @@ trait OpenStackTestEntityTrait {
   * @param string $name
   *   The network name.
   * @param string $network_id
   *   The network id.
   *   The network ID.
   * @param string $project_id
   *   The project id.
   *   The project ID.
   * @param string $admin_state_up
   *   The admin state up.
   * @param string $shared
@@ -320,13 +320,13 @@ trait OpenStackTestEntityTrait {
   * @param string $name
   *   The subnet name.
   * @param string $subnet_id
   *   The subnet id.
   *   The subnet ID.
   * @param string $network_id
   *   The network id.
   *   The network ID.
   * @param string $project_id
   *   The project id.
   *   The project ID.
   * @param string $subnet_pool_id
   *   The subnet pool id.
   *   The subnet pool ID.
   * @param string $ip_version
   *   The ip version.
   * @param string $cidr
@@ -387,4 +387,94 @@ trait OpenStackTestEntityTrait {
    ]);
  }

  /**
   * Create an Open Stack port test entity.
   *
   * @param string $class
   *   The network class.
   * @param int $index
   *   The Index.
   * @param string $cloud_context
   *   The cloud context.
   * @param string $name
   *   The network name.
   * @param string $port_id
   *   The port ID.
   * @param string $network_id
   *   The network ID.
   * @param string $project_id
   *   The project ID.
   * @param string $mac_address
   *   The mac address.
   * @param string $admin_state_up
   *   The admin state up.
   * @param string $port_security_enabled
   *   The port security enabled.
   * @param string $dns_name
   *   The dns name.
   * @param string $dns_assignment
   *   The dns assignment.
   * @param array $fixed_ips
   *   The fixed ips.
   * @param string $device_owner
   *   The device owner.
   * @param string $device_id
   *   The device ID.
   * @param array $security_groups
   *   The security groups.
   *
   * @return \Drupal\cloud\Entity\CloudContentEntityBase
   *   The network entity.
   *
   * @throws \Exception
   */
  protected function createPortTestEntity(
    string $class,
    int $index = 0,
    string $cloud_context = '',
    string $name = '',
    string $port_id = '',
    string $network_id = '',
    string $project_id = '',
    string $mac_address = '',
    string $admin_state_up = '',
    string $port_security_enabled = '',
    string $dns_name = '',
    string $dns_assignment = '',
    array $fixed_ips = [],
    string $device_owner = '',
    string $device_id = '',
    array $security_groups = []
  ): CloudContentEntityBase {
    $timestamp = time();

    return $this->createTestEntity($class, [
      'cloud_context' => $cloud_context,
      'name' => $name ?: sprintf('port-entity #%d - %s - %s', $index + 1, date('Y/m/d H:i:s'), $this->random->name(32, TRUE)),
      'port_id' => $port_id ?: 'port-' . $this->getRandomId(),
      'network_id' => $network_id ?: 'network-' . $this->getRandomId(),
      'project_id' => $project_id ?: 'project-' . $this->getRandomId(),
      'mac_address' => $mac_address,
      'admin_state_up' => $admin_state_up,
      'port_security_enabled' => $port_security_enabled,
      'dns_name' => $dns_name,
      'dns_assignment' => $dns_assignment,
      'fixed_ips' => $fixed_ips,
      'device_owner' => $device_owner,
      'device_id' => $device_id,
      'security_groups' => $security_groups,
      'binding_vnic_type' => '',
      'binding_host_id' => '',
      'binding_profile' => '',
      'binding_vif_type' => '',
      'binding_vif_details' => '',
      'allowed_address_pairs' => '',
      'status' => 'ACTIVE',
      'created' => $timestamp,
      'changed' => $timestamp,
      'refreshed' => $timestamp,
      'uid' => $this->loggedInUser->id(),
    ]);
  }

}
+53 −0
Original line number Diff line number Diff line
@@ -488,4 +488,57 @@ trait OpenStackTestFormDataTrait {
    return $subnets;
  }

  /**
   * Create port test data.
   *
   * @param int $repeat_count
   *   Repeat count.
   *
   * @return array
   *   test data array.
   */
  protected function createPortTestFormData(int $repeat_count): array {
    $data = [];
    $ip_address_or_subnets = [
      'subnet',
      'fixed_ip',
    ];
    $ip_address_or_subnet = $ip_address_or_subnets[random_int(0, 1)];

    for ($i = 0, $num = 1; $i < $repeat_count; $i++, $num++) {
      $ip_address_or_subnet = $ip_address_or_subnets[$i];
      $data[$i] = [
        'name' => "port-name #$num - {$this->random->name(32, TRUE)}",
        'network_id' => "network-{$this->getRandomId()}",
        'device_id' => "device-{$this->getRandomId()}",
        'device_owner' => 'network:{$this->getRandomId()}',
        'ip_address_or_subnet' => $ip_address_or_subnet,
        'subnet' => "subnet-{$this->getRandomId()}",
        'fixed_ips' => Utils::getRandomPublicIp(),
      ];
    }
    return $data;
  }

  /**
   * Create random port data.
   *
   * @return array
   *   Random port data.
   *
   * @throws \Exception
   */
  protected function createPortsRandomTestFormData(): array {
    $ports = [];
    $count = random_int(1, 10);
    for ($i = 0, $num = 1; $i < $count; $i++, $num++) {
      $ports[] = [
        'PortId' => "port-{$this->getRandomId()}",
        'Name' => sprintf('port-random-data #%d - %s - %s', $num, date('Y/m/d H:i:s'), $this->random->name(32, TRUE)),
      ];
    }

    return $ports;
  }

}
Loading