Skip to content

Commit ec7167a

Browse files
authored
Merge pull request #31 from volt-test/release/v1.2.x-dev
Release/v1.2.x dev
2 parents 64c42c4 + 48a7da1 commit ec7167a

32 files changed

Lines changed: 2625 additions & 46 deletions

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ name: CI
22

33
on:
44
push:
5-
branches: [ main, develop ]
5+
branches: [ main, develop, release/* ]
66
pull_request:
7-
branches: [ main, develop ]
7+
branches: [ main, develop , release/* ]
88

99
jobs:
1010
test:

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "volt-test/php-sdk",
33
"description": "Volt Test PHP SDK - A performance testing tool for PHP Developers",
44
"type": "library",
5-
"version": "1.1.1",
5+
"version": "1.2.2-dev",
66
"keywords": [
77
"volt-test",
88
"php-sdk",

src/CloudRun.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
namespace VoltTest;
4+
5+
class CloudRun
6+
{
7+
private const DASHBOARD_BASE_URL = 'https://volt-test.com';
8+
9+
private string $runId;
10+
11+
private string $testId;
12+
13+
private string $status;
14+
15+
public function __construct(string $runId, string $testId, string $status)
16+
{
17+
$this->runId = $runId;
18+
$this->testId = $testId;
19+
$this->status = $status;
20+
}
21+
22+
public function getRunId(): string
23+
{
24+
return $this->runId;
25+
}
26+
27+
public function getTestId(): string
28+
{
29+
return $this->testId;
30+
}
31+
32+
public function getStatus(): string
33+
{
34+
return $this->status;
35+
}
36+
37+
public function getDashboardUrl(): string
38+
{
39+
return self::DASHBOARD_BASE_URL . '/runs/' . $this->runId;
40+
}
41+
42+
public function isSuccessful(): bool
43+
{
44+
return $this->status === 'completed';
45+
}
46+
}

src/Configuration.php

Lines changed: 148 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,16 @@ class Configuration
1818

1919
private array $target;
2020

21+
private string $httpTimeout = '';
22+
2123
private bool $httpDebug = false;
2224

25+
/** @var Stage[] */
26+
private array $stages = [];
27+
28+
/** @var array<string, int> */
29+
private array $regionConfig = [];
30+
2331
public function __construct(string $name, string $description = '')
2432
{
2533
$this->name = $name;
@@ -38,15 +46,34 @@ public function toArray(): array
3846
$array = [
3947
'name' => $this->name,
4048
'description' => $this->description,
41-
'virtual_users' => $this->virtualUsers,
4249
'target' => $this->target,
4350
'http_debug' => $this->httpDebug,
4451
];
45-
if (trim($this->rampUp) !== '') {
46-
$array['ramp_up'] = $this->rampUp;
52+
53+
if (count($this->stages) > 0) {
54+
// Stages mode: omit virtual_users, duration, ramp_up
55+
$array['stages'] = array_map(fn (Stage $s) => $s->toArray(), $this->stages);
56+
} else {
57+
// Constant mode
58+
$array['virtual_users'] = $this->virtualUsers;
59+
if (trim($this->rampUp) !== '') {
60+
$array['ramp_up'] = $this->rampUp;
61+
}
62+
if (trim($this->duration) !== '') {
63+
$array['duration'] = $this->duration;
64+
}
4765
}
48-
if (trim($this->duration) !== '') {
49-
$array['duration'] = $this->duration;
66+
67+
if (trim($this->httpTimeout) !== '') {
68+
$array['http_timeout'] = $this->httpTimeout;
69+
}
70+
71+
if (count($this->regionConfig) > 0) {
72+
$array['region_config'] = array_map(
73+
fn (string $region, int $weight) => ['region' => $region, 'weight' => $weight],
74+
array_keys($this->regionConfig),
75+
array_values($this->regionConfig)
76+
);
5077
}
5178

5279
return $array;
@@ -82,7 +109,21 @@ public function setRampUp(string $rampUp): self
82109
return $this;
83110
}
84111

85-
public function setTarget(string $idleTimeout = '30s'): self
112+
public function setTargetUrl(string $url): self
113+
{
114+
if (! preg_match('/^https?:\/\//', $url)) {
115+
throw new VoltTestException('Target URL must start with http:// or https://');
116+
}
117+
$parsed = parse_url($url);
118+
if ($parsed === false || ! isset($parsed['host'])) {
119+
throw new VoltTestException('Invalid target URL');
120+
}
121+
$this->target['url'] = $url;
122+
123+
return $this;
124+
}
125+
126+
public function setIdleTimeout(string $idleTimeout = '30s'): self
86127
{
87128
if (! preg_match('/^\d+[smh]$/', $idleTimeout)) {
88129
throw new VoltTestException('Invalid idle timeout format. Use <number>[s|m|h]');
@@ -92,10 +133,111 @@ public function setTarget(string $idleTimeout = '30s'): self
92133
return $this;
93134
}
94135

136+
/**
137+
* @deprecated Use setIdleTimeout() instead
138+
*/
139+
public function setTarget(string $idleTimeout = '30s'): self
140+
{
141+
return $this->setIdleTimeout($idleTimeout);
142+
}
143+
144+
public function setHttpTimeout(string $httpTimeout): self
145+
{
146+
if (! preg_match('/^\d+[smh]$/', $httpTimeout)) {
147+
throw new VoltTestException('Invalid HTTP timeout format. Use <number>[s|m|h]');
148+
}
149+
$this->httpTimeout = $httpTimeout;
150+
151+
return $this;
152+
}
153+
95154
public function setHttpDebug(bool $httpDebug): self
96155
{
97156
$this->httpDebug = $httpDebug;
98157

99158
return $this;
100159
}
160+
161+
/**
162+
* @throws VoltTestException
163+
*/
164+
public function addStage(string $duration, int $target): self
165+
{
166+
$this->stages[] = new Stage($duration, $target);
167+
168+
return $this;
169+
}
170+
171+
public function hasStages(): bool
172+
{
173+
return count($this->stages) > 0;
174+
}
175+
176+
public function hasConstantLoad(): bool
177+
{
178+
return $this->virtualUsers > 1 || trim($this->duration) !== '' || trim($this->rampUp) !== '';
179+
}
180+
181+
public function clearConstantLoad(): self
182+
{
183+
$this->virtualUsers = 1;
184+
$this->duration = '';
185+
$this->rampUp = '';
186+
187+
return $this;
188+
}
189+
190+
/**
191+
* @param array $regions Region code => weight (e.g., ['us-east-1' => 60, 'eu-west-1' => 40])
192+
*
193+
* @throws VoltTestException
194+
*/
195+
public function setRegions(array $regions): self
196+
{
197+
if (empty($regions)) {
198+
throw new VoltTestException('Region distribution cannot be empty');
199+
}
200+
201+
foreach ($regions as $region => $weight) {
202+
if (! is_string($region) || trim($region) === '') {
203+
throw new VoltTestException('Region code must be a non-empty string');
204+
}
205+
206+
if (! is_int($weight)) {
207+
throw new VoltTestException('Region weight must be an integer');
208+
}
209+
210+
if ($weight <= 0) {
211+
throw new VoltTestException('Region weight must be greater than 0');
212+
}
213+
}
214+
215+
$sum = array_sum($regions);
216+
if ($sum !== 100) {
217+
throw new VoltTestException("Region weights must sum to 100, got {$sum}");
218+
}
219+
220+
$this->regionConfig = $regions;
221+
222+
return $this;
223+
}
224+
225+
public function hasRegions(): bool
226+
{
227+
return count($this->regionConfig) > 0;
228+
}
229+
230+
public function setName(string $name): self
231+
{
232+
$this->name = $name;
233+
234+
return $this;
235+
}
236+
237+
public function setDescription(string $description): self
238+
{
239+
$this->description = $description;
240+
241+
return $this;
242+
}
101243
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace VoltTest\Exceptions;
4+
5+
class AuthenticationException extends CloudException
6+
{
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace VoltTest\Exceptions;
4+
5+
class CloudConnectionException extends CloudException
6+
{
7+
}

src/Exceptions/CloudException.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace VoltTest\Exceptions;
4+
5+
class CloudException extends VoltTestException
6+
{
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace VoltTest\Exceptions;
4+
5+
class CloudTimeoutException extends CloudException
6+
{
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace VoltTest\Exceptions;
4+
5+
class PlanLimitException extends CloudException
6+
{
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace VoltTest\Exceptions;
4+
5+
class RunFailedException extends CloudException
6+
{
7+
}

0 commit comments

Comments
 (0)