Skip to content

Commit 2081e95

Browse files
authored
Merge pull request #68 from neo4j-php/testkit
merged testkit into main
2 parents 8f5944a + 95f6090 commit 2081e95

File tree

117 files changed

+4839
-218
lines changed

Some content is hidden

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

117 files changed

+4839
-218
lines changed

.github/workflows/testkit.yml

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
name: Testkit Tests
2+
3+
on:
4+
push:
5+
branches: [ '**' ]
6+
pull_request:
7+
branches: ['**']
8+
9+
jobs:
10+
tests:
11+
runs-on: ubuntu-latest
12+
name: "Running Testkit tests for PHP ${{matrix.php-version}} on Neo4j and testkit ${{ matrix.neo4j-version }} with simple config"
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
neo4j-version: ["3.5", "4.0", "4.1", "4.2", "4.3"]
17+
php-version: ["7.4", "8.0", "8.1"]
18+
19+
services:
20+
neo4j:
21+
image: neo4j:${{ matrix.neo4j-version }}
22+
env:
23+
NEO4J_AUTH: neo4j/test
24+
NEO4JLABS_PLUGINS: '["apoc"]'
25+
ports:
26+
- 7687:7687
27+
- 7474:7474
28+
options: >-
29+
--health-cmd "wget http://localhost:7474 || exit 1"
30+
31+
steps:
32+
- name: Checkout driver
33+
uses: actions/checkout@v2
34+
35+
- uses: php-actions/composer@v6
36+
with:
37+
progress: yes
38+
php_version: ${{ matrix.php-version }}
39+
version: 2
40+
41+
- name: Setup PHP
42+
uses: shivammathur/setup-php@v2
43+
with:
44+
php-version: ${{ matrix.php-version }}
45+
46+
- name: Checkout TestKit (testing tool)
47+
uses: actions/checkout@v2
48+
with:
49+
repository: neo4j-drivers/testkit
50+
path: testkit
51+
ref: '4.3'
52+
53+
- name: Install dependencies
54+
run: |
55+
sudo apt-get update
56+
# install docker
57+
sudo apt-get install \
58+
apt-transport-https \
59+
ca-certificates \
60+
curl \
61+
gnupg \
62+
lsb-release
63+
# Python (needed for dummy driver and TestKit)
64+
sudo apt-get install python3 python3-pip
65+
git clone https://github.com/pyenv/pyenv.git .pyenv
66+
python -m pip install --upgrade pip
67+
cd testkit
68+
python -m pip install -r requirements.txt
69+
70+
- name: Run TestKit
71+
env:
72+
TEST_NEO4J_HOST: localhost
73+
TEST_NEO4J_USER: neo4j
74+
TEST_NEO4J_PASS: test
75+
TEST_DRIVER_NAME: php
76+
run: |
77+
php testkit-backend/index.php &
78+
cd testkit
79+
sleep 2
80+
python3 -m unittest -v "tests.neo4j.test_authentication.TestAuthenticationBasic"

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ Auto committed queries are the most straightforward and most intuitive but have
119119
```php
120120
$client->run(
121121
'MERGE (user {email: $email})', //The query is a required parameter
122-
['email' => '[email protected]'], //Parameters can be optionally added
122+
['email' => '[email protected]'], //Requests can be optionally added
123123
'backup' //The default connection can be overridden
124124
);
125125
```

composer.json

+10-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"psr/http-client": "^1.0",
3232
"php-http/message": "^1.0",
3333
"php-http/message-factory": "^1.0",
34-
"stefanak-michal/bolt": "^2.5.2",
34+
"stefanak-michal/bolt": "^2.5.3",
3535
"symfony/polyfill-php80": "^1.2",
3636
"ext-json": "*"
3737
},
@@ -47,7 +47,13 @@
4747
"vimeo/psalm": "^4.13.0",
4848
"friendsofphp/php-cs-fixer": "3.0.2",
4949
"psalm/plugin-phpunit": "^0.15.1",
50-
"vlucas/phpdotenv": "^5.0"
50+
"monolog/monolog": "^2.2",
51+
"psr/log": "^1.1",
52+
"php-di/php-di": "^6.3",
53+
"vlucas/phpdotenv": "^5.0",
54+
"psr/container": "^1.1",
55+
"lctrs/psalm-psr-container-plugin": "^1.3",
56+
"symfony/uid": "^5.0"
5157
},
5258
"autoload": {
5359
"psr-4": {
@@ -56,7 +62,8 @@
5662
},
5763
"autoload-dev": {
5864
"psr-4": {
59-
"Laudis\\Neo4j\\Tests\\": "tests/"
65+
"Laudis\\Neo4j\\Tests\\": "tests/",
66+
"Laudis\\Neo4j\\TestkitBackend\\": "testkit-backend/src"
6067
}
6168
},
6269
"minimum-stability": "stable"

docker-compose.yml

+16
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,22 @@ services:
4141
- 9000
4242
env_file:
4343
- .env
44+
testkit-backend:
45+
build:
46+
context: .
47+
dockerfile: Dockerfile
48+
args:
49+
- WITH_XDEBUG=true
50+
working_dir: /opt/project
51+
volumes:
52+
- .:/opt/project
53+
command: php /opt/project/testkit-backend/index.php
54+
networks:
55+
- neo4j
56+
depends_on:
57+
- neo4j
58+
ports:
59+
- "9876:9876"
4460
neo4j:
4561
networks:
4662
- neo4j

psalm.xml

+8-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
>
1313
<projectFiles>
1414
<directory name="src"/>
15-
<directory ignoreTypeStats="true" name="tests"/>
15+
<directory name="tests"/>
16+
<directory name="testkit-backend"/>
1617
<ignoreFiles>
1718
<directory name="vendor"/>
1819
</ignoreFiles>
@@ -52,11 +53,17 @@
5253
<directory name="tests"/>
5354
</errorLevel>
5455
</MissingConstructor>
56+
<UncaughtThrowInGlobalScope>
57+
<errorLevel type="suppress">
58+
<file name="testkit-backend/index.php"/>
59+
</errorLevel>
60+
</UncaughtThrowInGlobalScope>
5561
</issueHandlers>
5662
<stubs>
5763
<file name="./vendor/vimeo/psalm/stubs/ext-ds.phpstub"/>
5864
</stubs>
5965
<plugins>
6066
<pluginClass class="Psalm\PhpUnitPlugin\Plugin"/>
67+
<pluginClass class="Lctrs\PsalmPsrContainerPlugin\Plugin"/>
6168
</plugins>
6269
</psalm>

src/Authentication/BasicAuth.php

+10-1
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@
1515

1616
use function base64_encode;
1717
use Bolt\Bolt;
18+
use Bolt\error\MessageException;
1819
use Exception;
20+
use Laudis\Neo4j\Common\TransactionHelper;
1921
use Laudis\Neo4j\Contracts\AuthenticateInterface;
22+
use Laudis\Neo4j\Databags\Neo4jError;
23+
use Laudis\Neo4j\Exception\Neo4jException;
2024
use Psr\Http\Message\RequestInterface;
2125
use Psr\Http\Message\UriInterface;
2226

@@ -58,7 +62,12 @@ public function authenticateHttp(RequestInterface $request, UriInterface $uri, s
5862
*/
5963
public function authenticateBolt(Bolt $bolt, UriInterface $uri, string $userAgent): void
6064
{
61-
$bolt->init($userAgent, $this->username, $this->password);
65+
try {
66+
$bolt->init($userAgent, $this->username, $this->password);
67+
} catch (MessageException $e) {
68+
$code = TransactionHelper::extractCode($e) ?? '';
69+
throw new Neo4jException([new Neo4jError($code, $e->getMessage())]);
70+
}
6271
}
6372

6473
/**

src/Bolt/BoltConfiguration.php

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
use function call_user_func;
1717
use function is_callable;
18+
use function is_string;
1819
use Laudis\Neo4j\Client;
1920
use Laudis\Neo4j\Contracts\ConfigInterface;
2021

src/Bolt/BoltConnectionPool.php

+2
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ public function acquire(
6464
if (!$connection->isOpen()) {
6565
$connection->open();
6666

67+
$authenticate->authenticateBolt($connection->getImplementation(), $connectingTo, $userAgent);
68+
6769
return $connection;
6870
}
6971
}

src/Client.php

+1-9
Original file line numberDiff line numberDiff line change
@@ -140,15 +140,7 @@ public function verifyConnectivity(?string $driver = null): bool
140140
*/
141141
private function decideAlias(?string $alias): string
142142
{
143-
if ($alias !== null) {
144-
return $alias;
145-
}
146-
147-
if ($this->default !== null) {
148-
return $this->default;
149-
}
150-
151-
return array_key_first($this->drivers);
143+
return $alias ?? $this->default ?? array_key_first($this->drivers);
152144
}
153145

154146
/**

src/Contracts/SessionInterface.php

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
namespace Laudis\Neo4j\Contracts;
1515

16+
use Laudis\Neo4j\Databags\Bookmark;
1617
use Laudis\Neo4j\Databags\Statement;
1718
use Laudis\Neo4j\Databags\TransactionConfiguration;
1819
use Laudis\Neo4j\Exception\Neo4jException;
@@ -95,4 +96,6 @@ public function readTransaction(callable $tsxHandler, ?TransactionConfiguration
9596
* @return HandlerResult
9697
*/
9798
public function transaction(callable $tsxHandler, ?TransactionConfiguration $config = null);
99+
100+
// public function getLastBookmark(): Bookmark;
98101
}

src/Databags/Bookmark.php

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Laudis Neo4j package.
7+
*
8+
* (c) Laudis technologies <http://laudis.tech>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Laudis\Neo4j\Databags;
15+
16+
use function bin2hex;
17+
use Exception;
18+
use function random_bytes;
19+
use function substr;
20+
21+
final class Bookmark
22+
{
23+
/** @var list<string> */
24+
private array $bookmarks;
25+
26+
/**
27+
* @param list<string> $bookmarks
28+
*/
29+
public function __construct(?array $bookmarks = null)
30+
{
31+
$this->bookmarks = $bookmarks ?? [];
32+
}
33+
34+
public function isEmpty(): bool
35+
{
36+
return count($this->bookmarks) === 0;
37+
}
38+
39+
/**
40+
* @return list<string>
41+
*/
42+
public function values(): array
43+
{
44+
return $this->bookmarks;
45+
}
46+
47+
/**
48+
* @throws Exception
49+
*/
50+
public function withIncrement(?string $bookmark = null): self
51+
{
52+
$copy = $this->bookmarks;
53+
if ($bookmark === null) {
54+
$bookmark = $this->generateUuidV4();
55+
}
56+
$copy[] = $bookmark;
57+
58+
return new self($copy);
59+
}
60+
61+
/**
62+
* @throws Exception
63+
*/
64+
private function generateUuidV4(): string
65+
{
66+
$uuid = random_bytes(16);
67+
$uuid[6] = ((int) $uuid[6]) & 0x0F | 0x40;
68+
$uuid[8] = ((int) $uuid[8]) & 0x3F | 0x80;
69+
$uuid = bin2hex($uuid);
70+
71+
return substr($uuid, 0, 8).'-'
72+
.substr($uuid, 8, 4).'-'
73+
.substr($uuid, 12, 4).'-'
74+
.substr($uuid, 16, 4).'-'
75+
.substr($uuid, 20, 12);
76+
}
77+
}

src/Databags/BookmarkHolder.php

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Laudis Neo4j package.
7+
*
8+
* (c) Laudis technologies <http://laudis.tech>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Laudis\Neo4j\Databags;
15+
16+
final class BookmarkHolder
17+
{
18+
private Bookmark $bookmark;
19+
20+
public function __construct(?Bookmark $bookmark = null)
21+
{
22+
$this->bookmark = $bookmark ?? new Bookmark();
23+
}
24+
25+
public function getBookmark(): Bookmark
26+
{
27+
return $this->bookmark;
28+
}
29+
30+
public function setBookmark(Bookmark $bookmark): void
31+
{
32+
$this->bookmark = $bookmark;
33+
}
34+
}

src/Databags/SessionConfiguration.php

+1
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ public function getAccessMode(): AccessMode
138138
{
139139
$accessMode = is_callable($this->accessMode) ? call_user_func($this->accessMode) : $this->accessMode;
140140

141+
/** @psalm-suppress ImpureMethodCall */
141142
return $accessMode ?? AccessMode::WRITE();
142143
}
143144

0 commit comments

Comments
 (0)