Skip to content

Commit c408ec2

Browse files
authored
Merge pull request #256 from neo4j-php/feat/testkit
feat: Bring Back Initial Testkit Support
2 parents c94c0f8 + 80656a4 commit c408ec2

File tree

98 files changed

+4623
-12
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+4623
-12
lines changed

.github/workflows/testkit.yml

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: Testkit Tests
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
9+
jobs:
10+
tests:
11+
runs-on: ubuntu-latest
12+
name: "Run Testkit Tests"
13+
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Restore Neo4j Image Cache if it exists
18+
id: cache-docker-neo4j
19+
uses: actions/cache@v4
20+
with:
21+
path: ci/cache/docker/neo4j
22+
key: cache-docker-neo4j-5-enterprise
23+
24+
- name: Update Neo4j Image Cache if cache miss
25+
if: steps.cache-docker-neo4j.outputs.cache-hit != 'true'
26+
run: |
27+
docker pull neo4j:5-enterprise
28+
mkdir -p ci/cache/docker/neo4j
29+
docker image save neo4j:5-enterprise --output ./ci/cache/docker/neo4j/neo4j-5-enterprise.tar
30+
31+
- name: Use Neo4j Image Cache if cache hit
32+
if: steps.cache-docker-neo4j.outputs.cache-hit == 'true'
33+
run: docker image load --input ./ci/cache/docker/neo4j/neo4j-5-enterprise.tar
34+
35+
- name: Set up Docker Buildx
36+
uses: docker/setup-buildx-action@v2
37+
38+
- name: Build & cache client image
39+
uses: docker/build-push-action@v3
40+
with:
41+
context: .
42+
file: Dockerfile
43+
load: true
44+
push: false
45+
cache-from: type=gha
46+
cache-to: type=gha,mode=max
47+
build-args: PHP_VERSION=8.1
48+
tags: integration-client:8.1
49+
50+
- name: Populate .env
51+
run: |
52+
echo "PHP_VERSION=8.1" > .env
53+
echo "CONNECTION=neo4j://neo4j:testtest@server1" >> .env
54+
55+
- name: Cache PHP deps
56+
id: cache-php-deps
57+
uses: actions/cache@v4
58+
with:
59+
path: vendor
60+
key: ${{ runner.os }}-php-8.1-${{ hashFiles('**/composer.json') }}
61+
restore-keys: |
62+
${{ runner.os }}-php-8.1-
63+
64+
- name: Install PHP deps
65+
if: steps.cache-php-deps.outputs.cache-hit != 'true'
66+
run: |
67+
docker compose run --rm client composer install
68+
69+
- name: Run integration tests
70+
run: |
71+
docker compose up -d --remove-orphans --wait --no-build \
72+
server1 \
73+
server2 \
74+
server3 \
75+
server4 \
76+
testkit_backend
77+
78+
docker compose run --rm testkit ./testkit.sh

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ composer.lock
1414
/docs/_build
1515
cachegrind.out.*
1616
.phpunit.cache/
17+
/testkit-backend/testkit/

.php-cs-fixer.dist.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333
try {
3434
$finder = PhpCsFixer\Finder::create()
3535
->in(__DIR__.'/src')
36-
->in(__DIR__.'/tests');
36+
->in(__DIR__.'/tests')
37+
->in(__DIR__.'/testkit-backend');
3738
} catch (Throwable $e) {
3839
echo $e->getMessage()."\n";
3940

composer.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@
5757
"cache/integration-tests": "dev-master",
5858
"kubawerlos/php-cs-fixer-custom-fixers": "3.13.*",
5959
"rector/rector": "^1.0",
60-
"psr/log": "^3.0"
60+
"psr/log": "^3.0",
61+
"php-di/php-di": "^6.3"
6162
},
6263
"autoload": {
6364
"psr-4": {
@@ -66,7 +67,8 @@
6667
},
6768
"autoload-dev": {
6869
"psr-4": {
69-
"Laudis\\Neo4j\\Tests\\": "tests/"
70+
"Laudis\\Neo4j\\Tests\\": "tests/",
71+
"Laudis\\Neo4j\\TestkitBackend\\": "testkit-backend/src"
7072
}
7173
},
7274
"minimum-stability": "stable",
@@ -81,6 +83,7 @@
8183
},
8284
"scripts": {
8385
"fix-cs": "./vendor/bin/php-cs-fixer fix",
86+
"check-cs": "./vendor/bin/php-cs-fixer fix --dry-run",
8487
"psalm": "./vendor/bin/psalm"
8588
}
8689
}

docker-compose.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ services:
6565
NEO4J_server_bolt_advertised__address: neo4j:7687
6666
NEO4J_server_http_advertised__address: neo4j:7474
6767

68+
69+
6870
server1:
6971
<<: *common-cluster
7072
hostname: server1
@@ -113,3 +115,32 @@ services:
113115
NEO4J_initial_server_mode__constraint: 'SECONDARY'
114116
NEO4J_server_bolt_advertised__address: server4:7687
115117
NEO4J_server_http_advertised__address: server4:7474
118+
119+
testkit:
120+
image: python:3.13
121+
volumes:
122+
- .:/opt/project
123+
working_dir: /opt/project/testkit-backend
124+
networks:
125+
- neo4j
126+
environment:
127+
TEST_NEO4J_HOST: neo4j
128+
TEST_NEO4J_USER: neo4j
129+
TEST_NEO4J_PASS: testtest
130+
TEST_DRIVER_NAME: php
131+
TEST_DRIVER_REPO: /opt/project
132+
TEST_BACKEND_HOST: testkit_backend
133+
134+
testkit_backend:
135+
<<: *common-php
136+
environment:
137+
PHP_IDE_CONFIG: "serverName=myserver"
138+
command: php -d xdebug.mode=debug -d xdebug.start_with_request=yes -d xdebug.client_host=host.docker.internal ./testkit-backend/index.php
139+
networks:
140+
- neo4j
141+
extra_hosts:
142+
- "host.docker.internal:host-gateway"
143+
depends_on:
144+
- neo4j
145+
ports:
146+
- "9876:9876"

src/Bolt/BoltConnection.php

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
use Psr\Http\Message\UriInterface;
3939
use Psr\Log\LogLevel;
4040
use Throwable;
41+
use Traversable;
4142
use WeakReference;
4243

4344
/**
@@ -209,12 +210,14 @@ public function reset(): void
209210
* Begins a transaction.
210211
*
211212
* Any of the preconditioned states are: 'READY', 'INTERRUPTED'.
213+
*
214+
* @param iterable<string, scalar|array|null>|null $txMetaData
212215
*/
213-
public function begin(?string $database, ?float $timeout, BookmarkHolder $holder): void
216+
public function begin(?string $database, ?float $timeout, BookmarkHolder $holder, ?iterable $txMetaData): void
214217
{
215218
$this->consumeResults();
216219

217-
$extra = $this->buildRunExtra($database, $timeout, $holder, AccessMode::WRITE());
220+
$extra = $this->buildRunExtra($database, $timeout, $holder, AccessMode::WRITE(), $txMetaData);
218221
$message = $this->messageFactory->createBeginMessage($extra);
219222
$response = $message->send()->getResponse();
220223
$this->assertNoFailure($response);
@@ -248,8 +251,9 @@ public function run(
248251
?float $timeout,
249252
BookmarkHolder $holder,
250253
?AccessMode $mode,
254+
?iterable $tsxMetadata,
251255
): array {
252-
$extra = $this->buildRunExtra($database, $timeout, $holder, $mode);
256+
$extra = $this->buildRunExtra($database, $timeout, $holder, $mode, $tsxMetadata);
253257
$message = $this->messageFactory->createRunMessage($text, $parameters, $extra);
254258
$response = $message->send()->getResponse();
255259
$this->assertNoFailure($response);
@@ -327,7 +331,7 @@ public function close(): void
327331
}
328332
}
329333

330-
private function buildRunExtra(?string $database, ?float $timeout, BookmarkHolder $holder, ?AccessMode $mode): array
334+
private function buildRunExtra(?string $database, ?float $timeout, BookmarkHolder $holder, ?AccessMode $mode, ?iterable $metadata): array
331335
{
332336
$extra = [];
333337
if ($database !== null) {
@@ -345,6 +349,13 @@ private function buildRunExtra(?string $database, ?float $timeout, BookmarkHolde
345349
$extra['mode'] = AccessMode::WRITE() === $mode ? 'w' : 'r';
346350
}
347351

352+
if ($metadata !== null) {
353+
$metadataArray = $metadata instanceof Traversable ? iterator_to_array($metadata) : $metadata;
354+
if (count($metadataArray) > 0) {
355+
$extra['tx_metadata'] = $metadataArray;
356+
}
357+
}
358+
348359
return $extra;
349360
}
350361

src/Bolt/BoltUnmanagedTransaction.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,8 @@ public function runStatement(Statement $statement): SummarizedResult
138138
$this->database,
139139
$this->tsxConfig->getTimeout(),
140140
$this->bookmarkHolder,
141-
$this->config->getAccessMode()
141+
$this->config->getAccessMode(),
142+
$this->tsxConfig->getMetaData()
142143
);
143144
} catch (Throwable $e) {
144145
$this->state = TransactionState::TERMINATED;

src/Bolt/Session.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ private function startTransaction(TransactionConfiguration $config, SessionConfi
188188
try {
189189
$connection = $this->acquireConnection($config, $sessionConfig);
190190

191-
$connection->begin($this->config->getDatabase(), $config->getTimeout(), $this->bookmarkHolder);
191+
$connection->begin($this->config->getDatabase(), $config->getTimeout(), $this->bookmarkHolder, $config->getMetaData());
192192
} catch (Neo4jException $e) {
193193
if (isset($connection) && $connection->getServerState() === 'FAILED') {
194194
$connection->reset();

src/Databags/ServerInfo.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public function toArray(): array
6161
{
6262
return [
6363
'address' => $this->address,
64-
'protocol' => $this->protocol,
64+
'protocolVersion' => $this->protocol,
6565
'agent' => $this->agent,
6666
];
6767
}

src/Types/CypherMap.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -572,8 +572,9 @@ public function getAsWGS843DPoint(string $key): WGS843DPoint
572572

573573
public function key(): string
574574
{
575-
/** @var string */
576-
return $this->cacheKey();
575+
// we have to cast to a string, as the value is potentially an integer if the key is numeric:
576+
// https://stackoverflow.com/questions/4100488/a-numeric-string-as-array-key-in-php
577+
return (string) $this->cacheKey();
577578
}
578579

579580
/**

0 commit comments

Comments
 (0)