def setUp(self):
     self.strategy = AllocateMissingValuesDeviceIndexStrategy()
    def __init__(self):
        self.image_waiter = AMIWaiter()
        self.command_result_parser = CommandResultsParser()
        self.cancellation_service = CommandCancellationService()
        self.client_err_wrapper = ClientErrorWrapper()
        self.tag_service = TagService(
            client_err_wrapper=self.client_err_wrapper)
        self.ec2_instance_waiter = InstanceWaiter(
            cancellation_service=self.cancellation_service)
        self.instance_service = InstanceService(self.tag_service,
                                                self.ec2_instance_waiter)
        self.ec2_storage_service = EC2StorageService()
        self.model_parser = AWSModelsParser()
        self.cloudshell_session_helper = CloudshellDriverHelper()
        self.aws_session_manager = AWSSessionProvider()
        self.password_waiter = PasswordWaiter(self.cancellation_service)
        self.vm_custom_params_extractor = VmCustomParamsExtractor()
        self.ami_credentials_service = InstanceCredentialsService(
            self.password_waiter)
        self.security_group_service = SecurityGroupService(self.tag_service)
        self.subnet_waiter = SubnetWaiter()
        self.subnet_service = SubnetService(self.tag_service,
                                            self.subnet_waiter)
        self.s3_service = S3BucketService()
        self.vpc_peering_waiter = VpcPeeringConnectionWaiter()
        self.key_pair_service = KeyPairService(self.s3_service)
        self.vpc_waiter = VPCWaiter()
        self.route_tables_service = RouteTablesService(self.tag_service)
        self.network_interface_service = NetworkInterfaceService(
            subnet_service=self.subnet_service,
            security_group_service=self.security_group_service,
        )
        self.elastic_ip_service = ElasticIpService()
        self.vm_details_provider = VmDetailsProvider()
        self.session_number_service = SessionNumberService()
        self.traffic_mirror_service = TrafficMirrorService()
        self.request_parser = DriverRequestParser()

        self.vpc_service = VPCService(
            tag_service=self.tag_service,
            subnet_service=self.subnet_service,
            instance_service=self.instance_service,
            vpc_waiter=self.vpc_waiter,
            vpc_peering_waiter=self.vpc_peering_waiter,
            sg_service=self.security_group_service,
            route_table_service=self.route_tables_service,
            traffic_mirror_service=self.traffic_mirror_service,
        )
        self.prepare_connectivity_operation = PrepareSandboxInfraOperation(
            vpc_service=self.vpc_service,
            security_group_service=self.security_group_service,
            key_pair_service=self.key_pair_service,
            tag_service=self.tag_service,
            route_table_service=self.route_tables_service,
            cancellation_service=self.cancellation_service,
            subnet_service=self.subnet_service,
            subnet_waiter=self.subnet_waiter,
        )

        self.deploy_ami_operation = DeployAMIOperation(
            instance_service=self.instance_service,
            ami_credential_service=self.ami_credentials_service,
            security_group_service=self.security_group_service,
            tag_service=self.tag_service,
            vpc_service=self.vpc_service,
            key_pair_service=self.key_pair_service,
            subnet_service=self.subnet_service,
            elastic_ip_service=self.elastic_ip_service,
            network_interface_service=self.network_interface_service,
            cancellation_service=self.cancellation_service,
            device_index_strategy=AllocateMissingValuesDeviceIndexStrategy(),
            vm_details_provider=self.vm_details_provider,
        )

        self.refresh_ip_operation = RefreshIpOperation(
            instance_service=self.instance_service)

        self.power_management_operation = PowerOperation(
            instance_service=self.instance_service,
            instance_waiter=self.ec2_instance_waiter,
        )

        self.delete_ami_operation = DeleteAMIOperation(
            instance_service=self.instance_service,
            ec2_storage_service=self.ec2_storage_service,
            security_group_service=self.security_group_service,
            tag_service=self.tag_service,
            elastic_ip_service=self.elastic_ip_service,
        )

        self.clean_up_operation = CleanupSandboxInfraOperation(
            vpc_service=self.vpc_service,
            key_pair_service=self.key_pair_service,
            route_table_service=self.route_tables_service,
            traffic_mirror_service=self.traffic_mirror_service,
        )

        self.deployed_app_ports_operation = DeployedAppPortsOperation(
            self.vm_custom_params_extractor,
            security_group_service=self.security_group_service,
            instance_service=self.instance_service,
        )

        self.access_key_operation = GetAccessKeyOperation(
            key_pair_service=self.key_pair_service)

        self.set_app_security_groups_operation = SetAppSecurityGroupsOperation(
            instance_service=self.instance_service,
            tag_service=self.tag_service,
            security_group_service=self.security_group_service,
        )

        self.vm_details_operation = VmDetailsOperation(
            instance_service=self.instance_service,
            vm_details_provider=self.vm_details_provider,
        )

        self.autoload_operation = AutoloadOperation()

        self.snapshot_operation = SnapshotOperation(self.instance_service,
                                                    self.image_waiter)

        self.traffic_mirroring_operation = TrafficMirrorOperation(
            tag_service=self.tag_service,
            session_number_service=self.session_number_service,
            traffic_mirror_service=self.traffic_mirror_service,
            cancellation_service=self.cancellation_service,
        )
class TestAllocateMissingValuesDeviceIndexStrategy(TestCase):
    def setUp(self):
        self.strategy = AllocateMissingValuesDeviceIndexStrategy()

    def test_strategy_allocates_missing_values_successfully(self):
        # arrange
        action1 = Mock(spec=PrepareCloudInfra)
        action1.actionParams = Mock(spec=ConnectToSubnetParams)
        action1.actionParams.vnicName = None

        action2 = Mock(spec=PrepareCloudInfra)
        action2.actionParams = Mock(spec=ConnectToSubnetParams)
        action2.actionParams.vnicName = 1

        action3 = Mock(spec=PrepareCloudInfra)
        action3.actionParams = Mock(spec=ConnectToSubnetParams)
        action3.actionParams.vnicName = None

        action4 = Mock(spec=PrepareCloudInfra)
        action4.actionParams = Mock(spec=ConnectToSubnetParams)
        action4.actionParams.vnicName = 3

        actions = [action1, action2, action3, action4]

        # act
        self.strategy.apply(actions)

        # assert
        # the order in witch the strategy assign device indexes is not guaranteed
        self.assertTrue(action1.actionParams.vnicName in [0, 2])
        self.assertTrue(action3.actionParams.vnicName in [0, 2])
        self.assertTrue(action1.actionParams.vnicName != action3.actionParams.vnicName)

    def test_strategy_allocates_missing_values_raises_on_device_index_duplicates(self):
        # arrange
        action1 = Mock(spec=PrepareCloudInfra)
        action1.actionParams = Mock(spec=ConnectToSubnetParams)
        action1.actionParams.vnicName = 1

        action2 = Mock(spec=PrepareCloudInfra)
        action2.actionParams = Mock(spec=ConnectToSubnetParams)
        action2.actionParams.vnicName = 1

        action3 = Mock(spec=PrepareCloudInfra)
        action3.actionParams = Mock(spec=ConnectToSubnetParams)
        action3.actionParams.vnicName = None

        actions = [action1, action2, action3]

        # act & assert
        with self.assertRaisesRegexp(ValueError, "Duplicate 'Requested vNic Name' attribute value found"):
            self.strategy.apply(actions)

    def test_strategy_allocates_missing_values_raises_when_not_continuous(self):
        # arrange
        action1 = Mock(spec=PrepareCloudInfra)
        action1.actionParams = MagicMock(spec=ConnectToSubnetParams)
        action1.actionParams.vnicName = 0

        action2 = Mock(spec=PrepareCloudInfra)
        action2.actionParams = MagicMock(spec=ConnectToSubnetParams)
        action2.actionParams.vnicName = 4

        action3 = Mock(spec=PrepareCloudInfra)
        action3.actionParams = MagicMock(spec=ConnectToSubnetParams)
        action3.actionParams.vnicName = None

        actions = [action1, action2, action3]

        # act & assert
        with self.assertRaisesRegexp(ValueError, "'Requested vNic Name' attribute values are not a continuous list"):
            self.strategy.apply(actions)

    def test_strategy_allocates_missing_values_no_changes_when_not_needed(self):
        # arrange
        action1 = Mock(spec=PrepareCloudInfra)
        action1.actionParams = MagicMock(spec=ConnectToSubnetParams)
        action1.actionParams.vnicName = 0

        action2 = Mock(spec=PrepareCloudInfra)
        action2.actionParams = MagicMock(spec=ConnectToSubnetParams)
        action2.actionParams.vnicName = 1

        action3 = Mock(spec=PrepareCloudInfra)
        action3.actionParams = MagicMock(spec=ConnectToSubnetParams)
        action3.actionParams.vnicName = 2

        actions = [action1, action2, action3]

        # act
        self.strategy.apply(actions)

        # assert
        # the order in witch the strategy assign device indexes is not guaranteed
        self.assertEquals(action1.actionParams.vnicName, 0)
        self.assertEquals(action2.actionParams.vnicName, 1)
        self.assertEquals(action3.actionParams.vnicName, 2)