BehatRetryExtension::loadRuntimeStepTester()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 5
rs 10
1
<?php namespace Chekote\BehatRetryExtension\ServiceContainer;
2
3
use Behat\Behat\Definition\ServiceContainer\DefinitionExtension;
4
use Behat\Testwork\Call\ServiceContainer\CallExtension;
5
use Behat\Testwork\ServiceContainer\Extension;
6
use Behat\Testwork\ServiceContainer\ExtensionManager;
7
use Chekote\BehatRetryExtension\Tester\RuntimeStepTester;
8
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
9
use Symfony\Component\DependencyInjection\ContainerBuilder;
10
use Symfony\Component\DependencyInjection\Definition;
11
use Symfony\Component\DependencyInjection\Reference;
12
13
/**
14
 * Extension for automatically retrying "Then" steps.
15
 */
16
class BehatRetryExtension implements Extension
17
{
18
    /** The service that our step tester needs to replace */
19
    const SERVICE_ID = 'tester.step.wrapper.hookable.inner';
20
21
    const CONFIG_KEY = 'spinner';
22
23
    const CONFIG_ENV_TIMEOUT = 'BEHAT_RETRY_TIMEOUT';
24
    const CONFIG_PARAM_ALL = 'parameters';
25
    const CONFIG_PARAM_INTERVAL = 'interval';
26
    const CONFIG_PARAM_TIMEOUT = 'timeout';
27
    const CONFIG_PARAM_STRICT_KEYWORDS = 'strictKeywords';
28
29
    const CONFIG_ALL = self::CONFIG_KEY . '.' . self::CONFIG_PARAM_ALL;
30
    const CONFIG_RETRY_INTERVAL = self::CONFIG_KEY . '.' . self::CONFIG_PARAM_INTERVAL;
31
    const CONFIG_TIMEOUT = self::CONFIG_KEY . '.' . self::CONFIG_PARAM_TIMEOUT;
32
    const CONFIG_STRICT_KEYWORDS = self::CONFIG_KEY . '.' . self::CONFIG_PARAM_STRICT_KEYWORDS;
33
34
    /**
35
     * {@inheritdoc}
36
     */
37
    public function process(ContainerBuilder $container)
38
    {
39
        $definition = new Definition(RuntimeStepTester::class, [
40
            new Reference(DefinitionExtension::FINDER_ID),
41
            new Reference(CallExtension::CALL_CENTER_ID),
42
        ]);
43
44
        $container->setDefinition(self::SERVICE_ID, $definition);
45
    }
46
47
    /**
48
     * {@inheritdoc}
49
     */
50
    public function getConfigKey()
51
    {
52
        return self::CONFIG_KEY;
53
    }
54
55
    /**
56
     * {@inheritdoc}
57
     */
58
    public function initialize(ExtensionManager $extensionManager)
59
    {
60
    }
61
62
    /**
63
     * {@inheritdoc}
64
     */
65
    public function configure(ArrayNodeDefinition $builder)
66
    {
67
        /* @scrutinizer ignore-call Scrutinizer does not understand the context that determines the return types  */
68
        $builder
69
            ->children()
70
                ->floatNode(self::CONFIG_PARAM_TIMEOUT)->defaultValue(5)->end()
71
                ->integerNode(self::CONFIG_PARAM_INTERVAL)->defaultValue(100000000)->end()
72
                ->booleanNode(self::CONFIG_PARAM_STRICT_KEYWORDS)->defaultTrue()->end()
73
            ->end()
74
        ->end();
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     */
80
    public function load(ContainerBuilder $container, array $config)
81
    {
82
        $container->setParameter(self::CONFIG_ALL, $config);
83
        $envTimeout = $this->getEnvTimeout();
84
        $container->setParameter(
85
            self::CONFIG_TIMEOUT,
86
            $envTimeout !== null ? $envTimeout : $config[self::CONFIG_PARAM_TIMEOUT]
87
        );
88
        $container->setParameter(self::CONFIG_RETRY_INTERVAL, $config[self::CONFIG_PARAM_INTERVAL]);
89
        $container->setParameter(self::CONFIG_STRICT_KEYWORDS, $config[self::CONFIG_PARAM_STRICT_KEYWORDS]);
90
91
        $this->loadRuntimeStepTester($container);
92
    }
93
94
    /**
95
     * Sets up up the RuntimeStepTester.
96
     *
97
     * The specified container should have a self::CONFIG_TIMEOUT and a self::CONFIG_RETRY_INTERVAL parameter.
98
     *
99
     * @param ContainerBuilder $container the container with the parameters to use.
100
     */
101
    private function loadRuntimeStepTester(ContainerBuilder $container)
102
    {
103
        RuntimeStepTester::$timeout = $container->getParameter(self::CONFIG_TIMEOUT);
104
        RuntimeStepTester::$interval = $container->getParameter(self::CONFIG_RETRY_INTERVAL);
105
        RuntimeStepTester::$strictKeywords = $container->getParameter(self::CONFIG_STRICT_KEYWORDS);
106
    }
107
108
    /**
109
     * Gets the timeout from the environment variable, if set.
110
     *
111
     * @return float|null the timeout in seconds, or null if not set or invalid.
112
     */
113
    private function getEnvTimeout(): ?float
114
    {
115
        $raw = getenv(self::CONFIG_ENV_TIMEOUT);
116
        if ($raw === false) {
117
            return null;
118
        }
119
120
        $value = trim($raw);
121
        if ($value === '') {
122
            return null;
123
        }
124
125
        if (!is_numeric($value)) {
126
            fwrite(STDERR, 'Warning: Environment variable ' . self::CONFIG_ENV_TIMEOUT .
127
                ' should be numeric (seconds), got "' . $raw . '"' . PHP_EOL);
128
129
            return null;
130
        }
131
132
        $numeric = (float) $value;
133
        if ($numeric < 0) {
134
            fwrite(STDERR, 'Warning: Environment variable ' . self::CONFIG_ENV_TIMEOUT .
135
                ' must be >= 0, got "' . $raw . '"' . PHP_EOL);
136
137
            return null;
138
        }
139
140
        return $numeric;
141
    }
142
}
143