diff --git a/benchkit-backend/LICENSES.txt b/benchkit-backend/LICENSES.txt index 836ba67225..995821f879 100644 --- a/benchkit-backend/LICENSES.txt +++ b/benchkit-backend/LICENSES.txt @@ -7,6 +7,10 @@ Apache Software License, Version 2.0 Jackson-annotations Jackson-core jackson-databind + Neo4j Bolt Connection (Netty reference impl) + Neo4j Bolt Connection (Pooled provider impl) + Neo4j Bolt Connection (Provider SPI) + Neo4j Bolt Connection (Routed provider impl) Netty/Buffer Netty/Codec Netty/Codec/HTTP diff --git a/benchkit-backend/NOTICE.txt b/benchkit-backend/NOTICE.txt index d1f14e0749..18004f5006 100644 --- a/benchkit-backend/NOTICE.txt +++ b/benchkit-backend/NOTICE.txt @@ -22,6 +22,10 @@ Apache Software License, Version 2.0 Jackson-annotations Jackson-core jackson-databind + Neo4j Bolt Connection (Netty reference impl) + Neo4j Bolt Connection (Pooled provider impl) + Neo4j Bolt Connection (Provider SPI) + Neo4j Bolt Connection (Routed provider impl) Netty/Buffer Netty/Codec Netty/Codec/HTTP diff --git a/benchkit-backend/pom.xml b/benchkit-backend/pom.xml index b93e063697..558f46dc1a 100644 --- a/benchkit-backend/pom.xml +++ b/benchkit-backend/pom.xml @@ -27,30 +27,6 @@ neo4j-java-driver ${project.version} - - org.neo4j.driver - neo4j-bolt-api - ${project.version} - true - - - org.neo4j.driver - neo4j-bolt-api-netty - ${project.version} - true - - - org.neo4j.driver - neo4j-bolt-api-pooled - ${project.version} - true - - - org.neo4j.driver - neo4j-bolt-api-routed - ${project.version} - true - io.netty netty-handler diff --git a/bolt-api-netty/LICENSES.txt b/bolt-api-netty/LICENSES.txt deleted file mode 100644 index 71c74a8f0f..0000000000 --- a/bolt-api-netty/LICENSES.txt +++ /dev/null @@ -1,221 +0,0 @@ -This file contains the full license text of the included third party -libraries. For an overview of the licenses see the NOTICE.txt file. - - ------------------------------------------------------------------------------- -Apache Software License, Version 2.0 - Netty/Buffer - Netty/Codec - Netty/Common - Netty/Handler - Netty/Resolver - Netty/TomcatNative [OpenSSL - Classes] - Netty/Transport - Netty/Transport/Native/Unix/Common ------------------------------------------------------------------------------- - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - - diff --git a/bolt-api-netty/NOTICE.txt b/bolt-api-netty/NOTICE.txt deleted file mode 100644 index 2cebea3b44..0000000000 --- a/bolt-api-netty/NOTICE.txt +++ /dev/null @@ -1,30 +0,0 @@ -Copyright (c) "Neo4j" -Neo4j Sweden AB [https://neo4j.com] - -This file is part of Neo4j. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -Full license texts are found in LICENSES.txt. - - -Third-party licenses --------------------- - -Apache Software License, Version 2.0 - Netty/Buffer - Netty/Codec - Netty/Common - Netty/Handler - Netty/Resolver - Netty/TomcatNative [OpenSSL - Classes] - Netty/Transport - Netty/Transport/Native/Unix/Common - diff --git a/bolt-api-netty/pom.xml b/bolt-api-netty/pom.xml deleted file mode 100644 index e637e93c5e..0000000000 --- a/bolt-api-netty/pom.xml +++ /dev/null @@ -1,85 +0,0 @@ - - 4.0.0 - - - org.neo4j.driver - neo4j-java-driver-parent - 5.28-SNAPSHOT - - - neo4j-bolt-api-netty - - jar - Neo4j Bolt API Netty - https://github.com/neo4j/neo4j-java-driver - - - ${project.basedir}/.. - ,-try - --add-opens org.neo4j.bolt.netty/org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging=ALL-UNNAMED - - - - - org.neo4j.driver - neo4j-bolt-api - ${project.version} - - - io.netty - netty-handler - - - io.netty - netty-tcnative-classes - - - - org.neo4j.driver - neo4j-bolt-api-test-values - ${project.version} - test - - - org.mockito - mockito-core - - - org.junit.jupiter - junit-jupiter - - - - - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-javadoc-plugin - - - org.apache.maven.plugins - maven-failsafe-plugin - - - org.apache.maven.surefire - surefire-junit-platform - ${surefire.and.failsafe.version} - - - - - - - - scm:git:git://github.com/neo4j/neo4j-java-driver.git - scm:git:git@github.com:neo4j/neo4j-java-driver.git - https://github.com/neo4j/neo4j-java-driver - - - diff --git a/bolt-api-netty/src/main/java/module-info.java b/bolt-api-netty/src/main/java/module-info.java deleted file mode 100644 index 5be9054deb..0000000000 --- a/bolt-api-netty/src/main/java/module-info.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * The Neo4j Bolt API Netty implementation module. - */ -@SuppressWarnings({"requires-automatic", "requires-transitive-automatic"}) -module org.neo4j.bolt.netty { - exports org.neo4j.driver.internal.bolt.basicimpl; - - requires transitive org.neo4j.bolt.api; - requires io.netty.common; - requires io.netty.handler; - requires transitive io.netty.transport; - requires io.netty.buffer; - requires io.netty.codec; - requires io.netty.resolver; - requires transitive java.logging; -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/BootstrapFactory.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/BootstrapFactory.java deleted file mode 100644 index 1d8ef311db..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/BootstrapFactory.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl; - -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.EventLoopGroupFactory; - -public final class BootstrapFactory { - private BootstrapFactory() {} - - public static Bootstrap newBootstrap(int threadCount) { - return newBootstrap(EventLoopGroupFactory.newEventLoopGroup(threadCount)); - } - - public static Bootstrap newBootstrap(EventLoopGroup eventLoopGroup) { - var bootstrap = new Bootstrap(); - bootstrap.group(eventLoopGroup); - bootstrap.channel(EventLoopGroupFactory.channelClass()); - bootstrap.option(ChannelOption.SO_KEEPALIVE, true); - bootstrap.option(ChannelOption.SO_REUSEADDR, true); - return bootstrap; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/EventLoopThread.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/EventLoopThread.java deleted file mode 100644 index c124a5f01b..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/EventLoopThread.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl; - -public interface EventLoopThread {} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/NettyBoltConnectionProvider.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/NettyBoltConnectionProvider.java deleted file mode 100644 index 0118675086..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/NettyBoltConnectionProvider.java +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl; - -import io.netty.channel.EventLoopGroup; -import io.netty.channel.local.LocalAddress; -import io.netty.util.internal.logging.InternalLoggerFactory; -import java.time.Clock; -import java.util.Collections; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; -import java.util.function.Supplier; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.AuthToken; -import org.neo4j.driver.internal.bolt.api.BoltAgent; -import org.neo4j.driver.internal.bolt.api.BoltConnection; -import org.neo4j.driver.internal.bolt.api.BoltConnectionProvider; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.DomainNameResolver; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.MetricsListener; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; -import org.neo4j.driver.internal.bolt.api.exception.MinVersionAcquisitionException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.BoltConnectionImpl; -import org.neo4j.driver.internal.bolt.basicimpl.impl.ConnectionProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.ConnectionProviders; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NettyLogging; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopMetricsListener; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v4.BoltProtocolV4; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v51.BoltProtocolV51; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.FutureUtil; - -public final class NettyBoltConnectionProvider implements BoltConnectionProvider { - private final LoggingProvider logging; - private final System.Logger log; - private final ConnectionProvider connectionProvider; - private final MetricsListener metricsListener; - private final Clock clock; - private final ValueFactory valueFactory; - - private CompletableFuture closeFuture; - - public NettyBoltConnectionProvider( - EventLoopGroup eventLoopGroup, - Clock clock, - DomainNameResolver domainNameResolver, - LocalAddress localAddress, - LoggingProvider logging, - ValueFactory valueFactory, - MetricsListener metricsListener) { - Objects.requireNonNull(eventLoopGroup); - this.clock = Objects.requireNonNull(clock); - this.logging = Objects.requireNonNull(logging); - this.log = logging.getLog(getClass()); - this.connectionProvider = ConnectionProviders.netty( - eventLoopGroup, clock, domainNameResolver, localAddress, logging, valueFactory); - this.valueFactory = Objects.requireNonNull(valueFactory); - this.metricsListener = NoopMetricsListener.getInstance(); - InternalLoggerFactory.setDefaultFactory(new NettyLogging(logging)); - } - - @Override - public CompletionStage connect( - BoltServerAddress address, - RoutingContext routingContext, - BoltAgent boltAgent, - String userAgent, - int connectTimeoutMillis, - SecurityPlan securityPlan, - DatabaseName databaseName, - Supplier> authTokenStageSupplier, - AccessMode mode, - Set bookmarks, - String impersonatedUser, - BoltProtocolVersion minVersion, - NotificationConfig notificationConfig, - Consumer databaseNameConsumer, - Map additionalParameters) { - synchronized (this) { - if (closeFuture != null) { - return CompletableFuture.failedFuture(new IllegalStateException("Connection provider is closed.")); - } - } - - var latestAuthMillisFuture = new CompletableFuture(); - var authMapRef = new AtomicReference(); - return authTokenStageSupplier - .get() - .thenCompose(authToken -> { - authMapRef.set(authToken); - return this.connectionProvider.acquireConnection( - address, - securityPlan, - routingContext, - databaseName != null ? databaseName.databaseName().orElse(null) : null, - authToken.asMap(), - boltAgent, - userAgent, - mode, - connectTimeoutMillis, - impersonatedUser, - latestAuthMillisFuture, - notificationConfig, - metricsListener); - }) - .thenCompose(connection -> { - if (minVersion != null - && minVersion.compareTo(connection.protocol().version()) > 0) { - return connection - .close() - .thenCompose( - (ignored) -> CompletableFuture.failedStage(new MinVersionAcquisitionException( - "lower version", - connection.protocol().version()))); - } else { - return CompletableFuture.completedStage(connection); - } - }) - .handle((connection, throwable) -> { - if (throwable != null) { - throwable = FutureUtil.completionExceptionCause(throwable); - log.log(System.Logger.Level.DEBUG, "Failed to establish BoltConnection " + address, throwable); - throw new CompletionException(throwable); - } else { - databaseNameConsumer.accept(databaseName); - return new BoltConnectionImpl( - connection.protocol(), - connection, - connection.eventLoop(), - authMapRef.get(), - latestAuthMillisFuture, - routingContext, - clock, - logging, - valueFactory); - } - }); - } - - @Override - public CompletionStage verifyConnectivity( - BoltServerAddress address, - RoutingContext routingContext, - BoltAgent boltAgent, - String userAgent, - int connectTimeoutMillis, - SecurityPlan securityPlan, - AuthToken authToken) { - return connect( - address, - routingContext, - boltAgent, - userAgent, - connectTimeoutMillis, - securityPlan, - null, - () -> CompletableFuture.completedStage(authToken), - AccessMode.WRITE, - Collections.emptySet(), - null, - null, - null, - (ignored) -> {}, - Collections.emptyMap()) - .thenCompose(BoltConnection::close); - } - - @Override - public CompletionStage supportsMultiDb( - BoltServerAddress address, - RoutingContext routingContext, - BoltAgent boltAgent, - String userAgent, - int connectTimeoutMillis, - SecurityPlan securityPlan, - AuthToken authToken) { - return connect( - address, - routingContext, - boltAgent, - userAgent, - connectTimeoutMillis, - securityPlan, - null, - () -> CompletableFuture.completedStage(authToken), - AccessMode.WRITE, - Collections.emptySet(), - null, - null, - null, - (ignored) -> {}, - Collections.emptyMap()) - .thenCompose(boltConnection -> { - var supports = boltConnection.protocolVersion().compareTo(BoltProtocolV4.VERSION) >= 0; - return boltConnection.close().thenApply(ignored -> supports); - }); - } - - @Override - public CompletionStage supportsSessionAuth( - BoltServerAddress address, - RoutingContext routingContext, - BoltAgent boltAgent, - String userAgent, - int connectTimeoutMillis, - SecurityPlan securityPlan, - AuthToken authToken) { - return connect( - address, - routingContext, - boltAgent, - userAgent, - connectTimeoutMillis, - securityPlan, - null, - () -> CompletableFuture.completedStage(authToken), - AccessMode.WRITE, - Collections.emptySet(), - null, - null, - null, - (ignored) -> {}, - Collections.emptyMap()) - .thenCompose(boltConnection -> { - var supports = BoltProtocolV51.VERSION.compareTo(boltConnection.protocolVersion()) <= 0; - return boltConnection.close().thenApply(ignored -> supports); - }); - } - - @Override - public CompletionStage close() { - CompletableFuture closeFuture; - synchronized (this) { - if (this.closeFuture == null) { - this.closeFuture = CompletableFuture.completedFuture(null); - } - closeFuture = this.closeFuture; - } - return closeFuture; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/BoltConnectionImpl.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/BoltConnectionImpl.java deleted file mode 100644 index 7c59f74ec4..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/BoltConnectionImpl.java +++ /dev/null @@ -1,748 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl; - -import io.netty.channel.EventLoop; -import io.netty.handler.codec.CodecException; -import java.io.IOException; -import java.time.Clock; -import java.time.Duration; -import java.util.ArrayDeque; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Queue; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Function; -import java.util.stream.Collectors; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.AuthInfo; -import org.neo4j.driver.internal.bolt.api.AuthToken; -import org.neo4j.driver.internal.bolt.api.BoltConnection; -import org.neo4j.driver.internal.bolt.api.BoltConnectionState; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.ResponseHandler; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; -import org.neo4j.driver.internal.bolt.api.TransactionType; -import org.neo4j.driver.internal.bolt.api.exception.BoltConnectionReadTimeoutException; -import org.neo4j.driver.internal.bolt.api.exception.BoltException; -import org.neo4j.driver.internal.bolt.api.exception.BoltFailureException; -import org.neo4j.driver.internal.bolt.api.exception.BoltProtocolException; -import org.neo4j.driver.internal.bolt.api.exception.BoltServiceUnavailableException; -import org.neo4j.driver.internal.bolt.api.exception.BoltUnsupportedFeatureException; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.CommitSummary; -import org.neo4j.driver.internal.bolt.api.summary.DiscardSummary; -import org.neo4j.driver.internal.bolt.api.summary.LogoffSummary; -import org.neo4j.driver.internal.bolt.api.summary.LogonSummary; -import org.neo4j.driver.internal.bolt.api.summary.PullSummary; -import org.neo4j.driver.internal.bolt.api.summary.ResetSummary; -import org.neo4j.driver.internal.bolt.api.summary.RollbackSummary; -import org.neo4j.driver.internal.bolt.api.summary.RouteSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.summary.TelemetrySummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.PullMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.FutureUtil; - -public final class BoltConnectionImpl implements BoltConnection { - private final LoggingProvider logging; - private final System.Logger log; - private final BoltProtocol protocol; - private final Connection connection; - private final EventLoop eventLoop; - private final String serverAgent; - private final BoltServerAddress serverAddress; - private final BoltProtocolVersion protocolVersion; - private final boolean telemetrySupported; - private final boolean serverSideRouting; - private final AtomicReference stateRef = new AtomicReference<>(BoltConnectionState.OPEN); - private final AtomicReference> authDataRef; - private final Map routingContext; - private final Queue>> messageWriters; - private final Clock clock; - private final ValueFactory valueFactory; - - public BoltConnectionImpl( - BoltProtocol protocol, - Connection connection, - EventLoop eventLoop, - AuthToken authToken, - CompletableFuture latestAuthMillisFuture, - RoutingContext routingContext, - Clock clock, - LoggingProvider logging, - ValueFactory valueFactory) { - this.protocol = Objects.requireNonNull(protocol); - this.connection = Objects.requireNonNull(connection); - this.eventLoop = Objects.requireNonNull(eventLoop); - this.serverAgent = Objects.requireNonNull(connection.serverAgent()); - this.serverAddress = Objects.requireNonNull(connection.serverAddress()); - this.protocolVersion = Objects.requireNonNull(connection.protocol().version()); - this.telemetrySupported = connection.isTelemetryEnabled(); - this.serverSideRouting = connection.isSsrEnabled(); - this.authDataRef = new AtomicReference<>( - CompletableFuture.completedFuture(new AuthInfoImpl(authToken, latestAuthMillisFuture.join()))); - this.valueFactory = Objects.requireNonNull(valueFactory); - this.routingContext = routingContext.toMap().entrySet().stream() - .collect(Collectors.toUnmodifiableMap( - Map.Entry::getKey, entry -> valueFactory.value(entry.getValue()), (a, b) -> b)); - this.messageWriters = new ArrayDeque<>(); - this.clock = Objects.requireNonNull(clock); - this.logging = Objects.requireNonNull(logging); - this.log = this.logging.getLog(getClass()); - } - - @Override - public CompletionStage onLoop() { - return executeInEventLoop(() -> {}).thenApply(ignored -> this); - } - - @Override - public CompletionStage route( - DatabaseName databaseName, String impersonatedUser, Set bookmarks) { - return executeInEventLoop(() -> messageWriters.add(handler -> protocol.route( - this.connection, - this.routingContext, - bookmarks, - databaseName.databaseName().orElse(null), - impersonatedUser, - new MessageHandler<>() { - @Override - public void onError(Throwable throwable) { - updateState(throwable); - handler.onError(throwable); - } - - @Override - public void onSummary(RouteSummary summary) { - handler.onRouteSummary(summary); - } - }, - clock, - logging, - valueFactory))) - .thenApply(ignored -> this); - } - - @Override - public CompletionStage beginTransaction( - DatabaseName databaseName, - AccessMode accessMode, - String impersonatedUser, - Set bookmarks, - TransactionType transactionType, - Duration txTimeout, - Map txMetadata, - String txType, - NotificationConfig notificationConfig) { - return executeInEventLoop(() -> messageWriters.add(handler -> protocol.beginTransaction( - this.connection, - databaseName, - accessMode, - impersonatedUser, - bookmarks, - txTimeout, - txMetadata, - txType, - notificationConfig, - new MessageHandler<>() { - @Override - public void onError(Throwable throwable) { - updateState(throwable); - handler.onError(throwable); - } - - @Override - public void onSummary(BeginSummary summary) { - handler.onBeginSummary(summary); - } - }, - logging, - valueFactory))) - .thenApply(ignored -> this); - } - - @Override - public CompletionStage runInAutoCommitTransaction( - DatabaseName databaseName, - AccessMode accessMode, - String impersonatedUser, - Set bookmarks, - String query, - Map parameters, - Duration txTimeout, - Map txMetadata, - NotificationConfig notificationConfig) { - return executeInEventLoop(() -> messageWriters.add(handler -> protocol.runAuto( - connection, - databaseName, - accessMode, - impersonatedUser, - query, - parameters, - bookmarks, - txTimeout, - txMetadata, - notificationConfig, - new MessageHandler<>() { - @Override - public void onError(Throwable throwable) { - updateState(throwable); - handler.onError(throwable); - } - - @Override - public void onSummary(RunSummary summary) { - handler.onRunSummary(summary); - } - }, - logging, - valueFactory))) - .thenApply(ignored -> this); - } - - @Override - public CompletionStage run(String query, Map parameters) { - return executeInEventLoop(() -> messageWriters.add( - handler -> protocol.run(connection, query, parameters, new MessageHandler<>() { - @Override - public void onError(Throwable throwable) { - updateState(throwable); - handler.onError(throwable); - } - - @Override - public void onSummary(RunSummary summary) { - handler.onRunSummary(summary); - } - }))) - .thenApply(ignored -> this); - } - - @Override - public CompletionStage pull(long qid, long request) { - return executeInEventLoop(() -> messageWriters.add(handler -> protocol.pull( - connection, - qid, - request, - new PullMessageHandler() { - @Override - public void onRecord(Value[] fields) { - handler.onRecord(fields); - } - - @Override - public void onError(Throwable throwable) { - updateState(throwable); - handler.onError(throwable); - } - - @Override - public void onSummary(PullSummary success) { - handler.onPullSummary(success); - } - }, - valueFactory))) - .thenApply(ignored -> this); - } - - @Override - public CompletionStage discard(long qid, long number) { - return executeInEventLoop(() -> messageWriters.add(handler -> protocol.discard( - this.connection, - qid, - number, - new MessageHandler<>() { - @Override - public void onError(Throwable throwable) { - updateState(throwable); - handler.onError(throwable); - } - - @Override - public void onSummary(DiscardSummary summary) { - handler.onDiscardSummary(summary); - } - }, - valueFactory))) - .thenApply(ignored -> this); - } - - @Override - public CompletionStage commit() { - return executeInEventLoop(() -> - messageWriters.add(handler -> protocol.commitTransaction(connection, new MessageHandler<>() { - @Override - public void onError(Throwable throwable) { - updateState(throwable); - handler.onError(throwable); - } - - @Override - public void onSummary(String bookmark) { - handler.onCommitSummary(() -> Optional.ofNullable(bookmark)); - } - }))) - .thenApply(ignored -> this); - } - - @Override - public CompletionStage rollback() { - return executeInEventLoop(() -> - messageWriters.add(handler -> protocol.rollbackTransaction(connection, new MessageHandler<>() { - @Override - public void onError(Throwable throwable) { - updateState(throwable); - handler.onError(throwable); - } - - @Override - public void onSummary(Void summary) { - handler.onRollbackSummary(RollbackSummaryImpl.INSTANCE); - } - }))) - .thenApply(ignored -> this); - } - - @Override - public CompletionStage reset() { - return executeInEventLoop( - () -> messageWriters.add(handler -> protocol.reset(connection, new MessageHandler<>() { - @Override - public void onError(Throwable throwable) { - updateState(throwable); - handler.onError(throwable); - } - - @Override - public void onSummary(Void summary) { - stateRef.set(BoltConnectionState.OPEN); - handler.onResetSummary(null); - } - }))) - .thenApply(ignored -> this); - } - - @Override - public CompletionStage logoff() { - return executeInEventLoop( - () -> messageWriters.add(handler -> protocol.logoff(connection, new MessageHandler<>() { - @Override - public void onError(Throwable throwable) { - updateState(throwable); - handler.onError(throwable); - } - - @Override - public void onSummary(Void summary) { - authDataRef.set(new CompletableFuture<>()); - handler.onLogoffSummary(null); - } - }))) - .thenApply(ignored -> this); - } - - @Override - public CompletionStage logon(AuthToken authToken) { - return executeInEventLoop(() -> messageWriters.add(handler -> protocol.logon( - connection, - authToken.asMap(), - clock, - new MessageHandler<>() { - @Override - public void onError(Throwable throwable) { - updateState(throwable); - handler.onError(throwable); - } - - @Override - public void onSummary(Void summary) { - authDataRef.get().complete(new AuthInfoImpl(authToken, clock.millis())); - handler.onLogonSummary(null); - } - }, - valueFactory))) - .thenApply(ignored -> this); - } - - @Override - public CompletionStage telemetry(TelemetryApi telemetryApi) { - return executeInEventLoop(() -> { - if (!telemetrySupported()) { - throw new BoltUnsupportedFeatureException("telemetry not supported"); - } else { - messageWriters.add(handler -> - protocol.telemetry(connection, telemetryApi.getValue(), new MessageHandler<>() { - @Override - public void onError(Throwable throwable) { - updateState(throwable); - handler.onError(throwable); - } - - @Override - public void onSummary(Void summary) { - handler.onTelemetrySummary(TelemetrySummaryImpl.INSTANCE); - } - })); - } - }) - .thenApply(ignored -> this); - } - - @Override - public CompletionStage clear() { - return executeInEventLoop(messageWriters::clear).thenApply(ignored -> this); - } - - @Override - public CompletionStage flush(ResponseHandler handler) { - var flushFuture = new CompletableFuture(); - return executeInEventLoop(() -> { - if (connection.isOpen()) { - var flushStage = CompletableFuture.completedStage(null); - var responseHandler = new ResponseHandleImpl(handler, messageWriters.size()); - var messageWriterIterator = messageWriters.iterator(); - while (messageWriterIterator.hasNext()) { - var messageWriter = messageWriterIterator.next(); - messageWriterIterator.remove(); - flushStage = flushStage.thenCompose(ignored -> messageWriter.apply(responseHandler)); - } - flushStage.thenCompose(ignored -> connection.flush()).whenComplete((ignored, throwable) -> { - if (throwable != null) { - throwable = FutureUtil.completionExceptionCause(throwable); - if (throwable instanceof CodecException - && throwable.getCause() instanceof IOException) { - var serviceError = new BoltServiceUnavailableException( - "Connection to the database failed", throwable.getCause()); - forceClose("Connection has been closed due to encoding error") - .whenComplete((ignored1, ignored2) -> - flushFuture.completeExceptionally(serviceError)); - } else { - flushFuture.completeExceptionally(throwable); - } - } else { - flushFuture.complete(null); - log.log(System.Logger.Level.DEBUG, "flushed"); - } - }); - } else { - throw new BoltServiceUnavailableException("Connection is closed"); - } - }) - .thenCompose(ignored -> flushFuture); - } - - @Override - public CompletionStage forceClose(String reason) { - if (stateRef.getAndSet(BoltConnectionState.CLOSED) != BoltConnectionState.CLOSED) { - try { - return connection.forceClose(reason).exceptionally(ignored -> null); - } catch (Throwable throwable) { - return CompletableFuture.completedStage(null); - } - } else { - return CompletableFuture.completedFuture(null); - } - } - - @Override - public CompletionStage close() { - CompletionStage close; - try { - close = switch (stateRef.getAndSet(BoltConnectionState.CLOSED)) { - case OPEN -> connection.close(); - case ERROR -> connection.forceClose("Closing connection after error"); - case FAILURE -> connection.forceClose("Closing connection after failure"); - case CLOSED -> CompletableFuture.completedStage(null);}; - } catch (Throwable throwable) { - close = CompletableFuture.completedStage(null); - } - return close.exceptionally(ignored -> null); - } - - @Override - public CompletionStage setReadTimeout(Duration duration) { - return executeInEventLoop(() -> connection.setReadTimeout(duration)); - } - - @Override - public BoltConnectionState state() { - var state = stateRef.get(); - if (state == BoltConnectionState.OPEN) { - if (!connection.isOpen()) { - state = BoltConnectionState.CLOSED; - } - } - return state; - } - - @Override - public CompletionStage authInfo() { - return authDataRef.get(); - } - - @Override - public String serverAgent() { - return serverAgent; - } - - @Override - public BoltServerAddress serverAddress() { - return serverAddress; - } - - @Override - public BoltProtocolVersion protocolVersion() { - return protocolVersion; - } - - @Override - public boolean telemetrySupported() { - return telemetrySupported; - } - - @Override - public boolean serverSideRoutingEnabled() { - return serverSideRouting; - } - - @Override - public Optional defaultReadTimeout() { - return connection.defaultReadTimeoutMillis(); - } - - private CompletionStage executeInEventLoop(Runnable runnable) { - var executeFuture = new CompletableFuture(); - Runnable stageCompletingRunnable = () -> { - try { - runnable.run(); - } catch (Throwable throwable) { - executeFuture.completeExceptionally(throwable); - } - executeFuture.complete(null); - }; - if (eventLoop.inEventLoop()) { - stageCompletingRunnable.run(); - } else { - try { - eventLoop.execute(stageCompletingRunnable); - } catch (Throwable throwable) { - executeFuture.completeExceptionally(throwable); - } - } - return executeFuture; - } - - private void updateState(Throwable throwable) { - if (throwable instanceof BoltServiceUnavailableException) { - if (throwable instanceof BoltConnectionReadTimeoutException) { - stateRef.compareAndExchange(BoltConnectionState.OPEN, BoltConnectionState.ERROR); - } else { - stateRef.set(BoltConnectionState.CLOSED); - } - } else if (throwable instanceof BoltFailureException boltFailureException) { - if ("Neo.ClientError.Security.AuthorizationExpired".equals(boltFailureException.code())) { - stateRef.compareAndExchange(BoltConnectionState.OPEN, BoltConnectionState.ERROR); - } else { - stateRef.compareAndExchange(BoltConnectionState.OPEN, BoltConnectionState.FAILURE); - } - } else if (throwable instanceof MessageIgnoredException) { - stateRef.compareAndExchange(BoltConnectionState.OPEN, BoltConnectionState.FAILURE); - } else { - stateRef.updateAndGet(state -> switch (state) { - case OPEN, FAILURE, ERROR -> BoltConnectionState.ERROR; - case CLOSED -> BoltConnectionState.CLOSED; - }); - } - } - - private record AuthInfoImpl(AuthToken authToken, long authAckMillis) implements AuthInfo {} - - private static class ResponseHandleImpl implements ResponseHandler { - private final ResponseHandler delegate; - private final CompletableFuture summariesFuture = new CompletableFuture<>(); - private int expectedSummaries; - - private ResponseHandleImpl(ResponseHandler delegate, int expectedSummaries) { - this.delegate = Objects.requireNonNull(delegate); - this.expectedSummaries = expectedSummaries; - - summariesFuture.whenComplete((ignored1, ignored2) -> onComplete()); - } - - @Override - public void onError(Throwable throwable) { - if (!(throwable instanceof MessageIgnoredException)) { - if (!summariesFuture.isDone()) { - runIgnoringError(() -> delegate.onError(throwable)); - if (!(throwable instanceof BoltException) - || throwable instanceof BoltServiceUnavailableException - || throwable instanceof BoltProtocolException) { - // assume unrecoverable error, ensure onComplete - expectedSummaries = 1; - } - handleSummary(); - } - } else { - onIgnored(); - } - } - - @Override - public void onBeginSummary(BeginSummary summary) { - if (!summariesFuture.isDone()) { - runIgnoringError(() -> delegate.onBeginSummary(summary)); - handleSummary(); - } - } - - @Override - public void onRunSummary(RunSummary summary) { - if (!summariesFuture.isDone()) { - runIgnoringError(() -> delegate.onRunSummary(summary)); - handleSummary(); - } - } - - @Override - public void onRecord(Value[] fields) { - if (!summariesFuture.isDone()) { - runIgnoringError(() -> delegate.onRecord(fields)); - } - } - - @Override - public void onPullSummary(PullSummary summary) { - if (!summariesFuture.isDone()) { - runIgnoringError(() -> delegate.onPullSummary(summary)); - handleSummary(); - } - } - - @Override - public void onDiscardSummary(DiscardSummary summary) { - if (!summariesFuture.isDone()) { - runIgnoringError(() -> delegate.onDiscardSummary(summary)); - handleSummary(); - } - } - - @Override - public void onCommitSummary(CommitSummary summary) { - if (!summariesFuture.isDone()) { - runIgnoringError(() -> delegate.onCommitSummary(summary)); - handleSummary(); - } - } - - @Override - public void onRollbackSummary(RollbackSummary summary) { - if (!summariesFuture.isDone()) { - runIgnoringError(() -> delegate.onRollbackSummary(summary)); - handleSummary(); - } - } - - @Override - public void onResetSummary(ResetSummary summary) { - if (!summariesFuture.isDone()) { - runIgnoringError(() -> delegate.onResetSummary(summary)); - handleSummary(); - } - } - - @Override - public void onRouteSummary(RouteSummary summary) { - if (!summariesFuture.isDone()) { - runIgnoringError(() -> delegate.onRouteSummary(summary)); - handleSummary(); - } - } - - @Override - public void onLogoffSummary(LogoffSummary summary) { - if (!summariesFuture.isDone()) { - runIgnoringError(() -> delegate.onLogoffSummary(summary)); - handleSummary(); - } - } - - @Override - public void onLogonSummary(LogonSummary summary) { - if (!summariesFuture.isDone()) { - runIgnoringError(() -> delegate.onLogonSummary(summary)); - handleSummary(); - } - } - - @Override - public void onTelemetrySummary(TelemetrySummary summary) { - if (!summariesFuture.isDone()) { - runIgnoringError(() -> delegate.onTelemetrySummary(summary)); - handleSummary(); - } - } - - @Override - public void onIgnored() { - if (!summariesFuture.isDone()) { - runIgnoringError(delegate::onIgnored); - handleSummary(); - } - } - - @Override - public void onComplete() { - runIgnoringError(delegate::onComplete); - } - - private void handleSummary() { - expectedSummaries--; - if (expectedSummaries == 0) { - summariesFuture.complete(null); - } - } - - private void runIgnoringError(Runnable runnable) { - try { - runnable.run(); - } catch (Throwable ignored) { - } - } - } - - private static class TelemetrySummaryImpl implements TelemetrySummary { - private static final TelemetrySummary INSTANCE = new TelemetrySummaryImpl(); - } - - private static class RollbackSummaryImpl implements RollbackSummary { - private static final RollbackSummary INSTANCE = new RollbackSummaryImpl(); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/ConnectionProvider.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/ConnectionProvider.java deleted file mode 100644 index 5492aa638f..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/ConnectionProvider.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl; - -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.BoltAgent; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.MetricsListener; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public interface ConnectionProvider { - - CompletionStage acquireConnection( - BoltServerAddress address, - SecurityPlan securityPlan, - RoutingContext routingContext, - String databaseName, - Map authMap, - BoltAgent boltAgent, - String userAgent, - AccessMode mode, - int connectTimeoutMillis, - String impersonatedUser, - CompletableFuture latestAuthMillisFuture, - NotificationConfig notificationConfig, - MetricsListener metricsListener); -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/ConnectionProviders.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/ConnectionProviders.java deleted file mode 100644 index 13ee068023..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/ConnectionProviders.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl; - -import io.netty.channel.EventLoopGroup; -import io.netty.channel.local.LocalAddress; -import java.time.Clock; -import org.neo4j.driver.internal.bolt.api.DomainNameResolver; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; - -public class ConnectionProviders { - public static ConnectionProvider netty( - EventLoopGroup group, - Clock clock, - DomainNameResolver domainNameResolver, - LocalAddress localAddress, - LoggingProvider logging, - ValueFactory valueFactory) { - return new NettyConnectionProvider(group, clock, domainNameResolver, localAddress, logging, valueFactory); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/MessageIgnoredException.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/MessageIgnoredException.java deleted file mode 100644 index 05a192ed00..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/MessageIgnoredException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl; - -import java.io.Serial; -import org.neo4j.driver.internal.bolt.api.exception.BoltException; - -public class MessageIgnoredException extends BoltException { - @Serial - private static final long serialVersionUID = 8087512561960062490L; - - public MessageIgnoredException(String message) { - super(message); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/NettyConnectionProvider.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/NettyConnectionProvider.java deleted file mode 100644 index 904370470c..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/NettyConnectionProvider.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl; - -import static java.util.Objects.requireNonNull; - -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.local.LocalAddress; -import io.netty.channel.local.LocalChannel; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.resolver.AddressResolverGroup; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.time.Clock; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.BoltAgent; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.DomainNameResolver; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.MetricsListener; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.NetworkConnection; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelConnectedListener; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelPipelineBuilderImpl; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.NettyChannelInitializer; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.NettyDomainNameResolverGroup; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.ConnectTimeoutHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public final class NettyConnectionProvider implements ConnectionProvider { - private final EventLoopGroup eventLoopGroup; - private final Clock clock; - private final DomainNameResolver domainNameResolver; - private final AddressResolverGroup addressResolverGroup; - private final LocalAddress localAddress; - - private final LoggingProvider logging; - private final ValueFactory valueFactory; - - public NettyConnectionProvider( - EventLoopGroup eventLoopGroup, - Clock clock, - DomainNameResolver domainNameResolver, - LocalAddress localAddress, - LoggingProvider logging, - ValueFactory valueFactory) { - this.eventLoopGroup = eventLoopGroup; - this.clock = requireNonNull(clock); - this.domainNameResolver = requireNonNull(domainNameResolver); - this.addressResolverGroup = new NettyDomainNameResolverGroup(this.domainNameResolver); - this.localAddress = localAddress; - this.logging = logging; - this.valueFactory = requireNonNull(valueFactory); - } - - @Override - public CompletionStage acquireConnection( - BoltServerAddress address, - SecurityPlan securityPlan, - RoutingContext routingContext, - String databaseName, - Map authMap, - BoltAgent boltAgent, - String userAgent, - AccessMode mode, - int connectTimeoutMillis, - String impersonatedUser, - CompletableFuture latestAuthMillisFuture, - NotificationConfig notificationConfig, - MetricsListener metricsListener) { - var bootstrap = new Bootstrap(); - bootstrap - .group(this.eventLoopGroup) - .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeoutMillis) - .channel(localAddress != null ? LocalChannel.class : NioSocketChannel.class) - .resolver(addressResolverGroup) - .handler(new NettyChannelInitializer(address, securityPlan, connectTimeoutMillis, clock, logging)); - - SocketAddress socketAddress; - if (localAddress == null) { - try { - socketAddress = - new InetSocketAddress(domainNameResolver.resolve(address.connectionHost())[0], address.port()); - } catch (Throwable t) { - socketAddress = InetSocketAddress.createUnresolved(address.connectionHost(), address.port()); - } - } else { - socketAddress = localAddress; - } - - return installChannelConnectedListeners(address, bootstrap.connect(socketAddress), connectTimeoutMillis) - .thenCompose(channel -> BoltProtocol.forChannel(channel) - .initializeChannel( - channel, - requireNonNull(userAgent), - requireNonNull(boltAgent), - authMap, - routingContext, - notificationConfig, - clock, - latestAuthMillisFuture, - valueFactory)) - .thenApply(channel -> new NetworkConnection(channel, logging)); - } - - private CompletionStage installChannelConnectedListeners( - BoltServerAddress address, ChannelFuture channelConnected, int connectTimeoutMillis) { - var pipeline = channelConnected.channel().pipeline(); - - // add timeout handler to the pipeline when channel is connected. it's needed to - // limit amount of time code - // spends in TLS and Bolt handshakes. prevents infinite waiting when database does - // not respond - channelConnected.addListener(future -> pipeline.addFirst(new ConnectTimeoutHandler(connectTimeoutMillis))); - - // add listener that sends Bolt handshake bytes when channel is connected - var handshakeCompleted = new CompletableFuture(); - channelConnected.addListener(new ChannelConnectedListener( - address, new ChannelPipelineBuilderImpl(), handshakeCompleted, logging, valueFactory)); - return handshakeCompleted.whenComplete((channel, throwable) -> { - if (throwable == null) { - // remove timeout handler from the pipeline once TLS and Bolt handshakes are - // completed. regular protocol - // messages will flow next and we do not want to have read timeout for them - channel.pipeline().remove(ConnectTimeoutHandler.class); - } - }); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/NettyLogger.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/NettyLogger.java deleted file mode 100644 index cb47dace96..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/NettyLogger.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl; - -import static java.lang.String.format; - -import io.netty.util.internal.logging.AbstractInternalLogger; -import java.io.Serial; -import java.util.regex.Pattern; - -public class NettyLogger extends AbstractInternalLogger { - @Serial - private static final long serialVersionUID = -1466889786216191159L; - - private final System.Logger log; - private static final Pattern PLACE_HOLDER_PATTERN = Pattern.compile("\\{}"); - - public NettyLogger(String name, System.Logger log) { - super(name); - this.log = log; - } - - @Override - public boolean isTraceEnabled() { - return log.isLoggable(System.Logger.Level.TRACE); - } - - @Override - public void trace(String msg) { - log.log(System.Logger.Level.TRACE, msg); - } - - @Override - public void trace(String format, Object arg) { - log.log(System.Logger.Level.TRACE, toDriverLoggerFormat(format), arg); - } - - @Override - public void trace(String format, Object argA, Object argB) { - log.log(System.Logger.Level.TRACE, toDriverLoggerFormat(format), argA, argB); - } - - @Override - public void trace(String format, Object... arguments) { - log.log(System.Logger.Level.TRACE, toDriverLoggerFormat(format), arguments); - } - - @Override - public void trace(String msg, Throwable t) { - log.log(System.Logger.Level.TRACE, "%s%n%s", msg, t); - } - - @Override - public boolean isDebugEnabled() { - return log.isLoggable(System.Logger.Level.DEBUG); - } - - @Override - public void debug(String msg) { - log.log(System.Logger.Level.DEBUG, msg); - } - - @Override - public void debug(String format, Object arg) { - log.log(System.Logger.Level.DEBUG, toDriverLoggerFormat(format), arg); - } - - @Override - public void debug(String format, Object argA, Object argB) { - log.log(System.Logger.Level.DEBUG, toDriverLoggerFormat(format), argA, argB); - } - - @Override - public void debug(String format, Object... arguments) { - log.log(System.Logger.Level.DEBUG, toDriverLoggerFormat(format), arguments); - } - - @Override - public void debug(String msg, Throwable t) { - log.log(System.Logger.Level.DEBUG, "%s%n%s", msg, t); - } - - @Override - public boolean isInfoEnabled() { - return true; - } - - @Override - public void info(String msg) { - log.log(System.Logger.Level.INFO, msg); - } - - @Override - public void info(String format, Object arg) { - log.log(System.Logger.Level.INFO, toDriverLoggerFormat(format), arg); - } - - @Override - public void info(String format, Object argA, Object argB) { - log.log(System.Logger.Level.INFO, toDriverLoggerFormat(format), argA, argB); - } - - @Override - public void info(String format, Object... arguments) { - log.log(System.Logger.Level.INFO, toDriverLoggerFormat(format), arguments); - } - - @Override - public void info(String msg, Throwable t) { - log.log(System.Logger.Level.INFO, "%s%n%s", msg, t); - } - - @Override - public boolean isWarnEnabled() { - return true; - } - - @Override - public void warn(String msg) { - log.log(System.Logger.Level.WARNING, msg); - } - - @Override - public void warn(String format, Object arg) { - log.log(System.Logger.Level.WARNING, toDriverLoggerFormat(format), arg); - } - - @Override - public void warn(String format, Object... arguments) { - log.log(System.Logger.Level.WARNING, toDriverLoggerFormat(format), arguments); - } - - @Override - public void warn(String format, Object argA, Object argB) { - log.log(System.Logger.Level.WARNING, toDriverLoggerFormat(format), argA, argB); - } - - @Override - public void warn(String msg, Throwable t) { - log.log(System.Logger.Level.WARNING, "%s%n%s", msg, t); - } - - @Override - public boolean isErrorEnabled() { - return true; - } - - @Override - public void error(String msg) { - log.log(System.Logger.Level.ERROR, msg, (Throwable) null); - } - - @Override - public void error(String format, Object arg) { - error(format, new Object[] {arg}); - } - - @Override - public void error(String format, Object argA, Object argB) { - error(format, new Object[] {argA, argB}); - } - - @Override - public void error(String format, Object... arguments) { - format = toDriverLoggerFormat(format); - if (arguments.length == 0) { - log.log(System.Logger.Level.ERROR, format, (Throwable) null); - return; - } - - var arg = arguments[arguments.length - 1]; - if (arg instanceof Throwable) { - // still give all arguments to string format, - // for the worst case, the redundant parameter will be ignored. - log.log(System.Logger.Level.ERROR, format(format, arguments), (Throwable) arg); - } - } - - @Override - public void error(String msg, Throwable t) { - log.log(System.Logger.Level.ERROR, msg, t); - } - - private String toDriverLoggerFormat(String format) { - return PLACE_HOLDER_PATTERN.matcher(format).replaceAll("%s"); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/NettyLogging.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/NettyLogging.java deleted file mode 100644 index 2bf3a94cb5..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/NettyLogging.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl; - -import io.netty.util.internal.logging.InternalLogger; -import io.netty.util.internal.logging.InternalLoggerFactory; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; - -/** - * This is the logging factory to delegate netty's logging to our logging system - */ -public class NettyLogging extends InternalLoggerFactory { - private final LoggingProvider logging; - - public NettyLogging(LoggingProvider logging) { - this.logging = logging; - } - - @Override - protected InternalLogger newInstance(String name) { - return new NettyLogger(name, logging.getLog(name)); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/NoopMetricsListener.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/NoopMetricsListener.java deleted file mode 100644 index 60b657b277..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/NoopMetricsListener.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl; - -import java.util.function.IntSupplier; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.ListenerEvent; -import org.neo4j.driver.internal.bolt.api.MetricsListener; - -public final class NoopMetricsListener implements MetricsListener { - private static final NoopMetricsListener INSTANCE = new NoopMetricsListener(); - - public static NoopMetricsListener getInstance() { - return INSTANCE; - } - - private NoopMetricsListener() {} - - @Override - public void beforeCreating(String poolId, ListenerEvent creatingEvent) {} - - @Override - public void afterCreated(String poolId, ListenerEvent creatingEvent) {} - - @Override - public void afterFailedToCreate(String poolId) {} - - @Override - public void afterClosed(String poolId) {} - - @Override - public void beforeAcquiringOrCreating(String poolId, ListenerEvent acquireEvent) {} - - @Override - public void afterAcquiringOrCreating(String poolId) {} - - @Override - public void afterAcquiredOrCreated(String poolId, ListenerEvent acquireEvent) {} - - @Override - public void afterTimedOutToAcquireOrCreate(String poolId) {} - - @Override - public void afterConnectionCreated(String poolId, ListenerEvent inUseEvent) {} - - @Override - public void afterConnectionReleased(String poolId, ListenerEvent inUseEvent) {} - - @Override - public ListenerEvent createListenerEvent() { - return new ListenerEvent<>() { - @Override - public void start() {} - - @Override - public Object getSample() { - return null; - } - }; - } - - @Override - public void registerPoolMetrics( - String poolId, BoltServerAddress serverAddress, IntSupplier inUseSupplier, IntSupplier idleSupplier) {} - - @Override - public void removePoolMetrics(String poolId) {} -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/NetworkConnection.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/NetworkConnection.java deleted file mode 100644 index 9907a54c14..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/NetworkConnection.java +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setTerminationReason; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.LockUtil.executeWithLock; - -import io.netty.channel.Channel; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandler; -import io.netty.channel.EventLoop; -import java.time.Duration; -import java.util.Collections; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.ConnectionReadTimeoutHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.NoOpResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.ResponseHandler; - -/** - * This connection represents a simple network connection to a remote server. It wraps a channel obtained from a connection pool. The life cycle of this - * connection start from the moment the channel is borrowed out of the pool and end at the time the connection is released back to the pool. - */ -public class NetworkConnection implements Connection { - private final System.Logger log; - private final Lock lock; - private final Channel channel; - private final InboundMessageDispatcher messageDispatcher; - private final String serverAgent; - private final BoltServerAddress serverAddress; - private final boolean telemetryEnabled; - private final boolean ssrEnabled; - private final BoltProtocol protocol; - - private final Duration defaultReadTimeout; - private Duration readTimeout; - - private ChannelHandler connectionReadTimeoutHandler; - - public NetworkConnection(Channel channel, LoggingProvider logging) { - this.log = logging.getLog(getClass()); - this.lock = new ReentrantLock(); - this.channel = channel; - this.messageDispatcher = ChannelAttributes.messageDispatcher(channel); - this.serverAgent = ChannelAttributes.serverAgent(channel); - this.serverAddress = ChannelAttributes.serverAddress(channel); - this.telemetryEnabled = ChannelAttributes.telemetryEnabled(channel); - this.ssrEnabled = ChannelAttributes.ssrEnabled(channel); - this.protocol = BoltProtocol.forChannel(channel); - this.defaultReadTimeout = ChannelAttributes.connectionReadTimeout(channel) - .map(Duration::ofSeconds) - .orElse(null); - this.readTimeout = defaultReadTimeout; - } - - @Override - public boolean isOpen() { - return executeWithLock(lock, channel::isOpen); - } - - @Override - public void enableAutoRead() { - if (isOpen()) { - setAutoRead(true); - } - } - - @Override - public void disableAutoRead() { - if (isOpen()) { - setAutoRead(false); - } - } - - @Override - public CompletionStage write(Message message, ResponseHandler handler) { - return writeMessageInEventLoop(message, handler); - } - - @Override - public CompletionStage flush() { - var future = new CompletableFuture(); - channel.eventLoop().execute(() -> { - channel.flush(); - future.complete(null); - }); - return future; - } - - @Override - public boolean isTelemetryEnabled() { - return telemetryEnabled; - } - - @Override - public boolean isSsrEnabled() { - return ssrEnabled; - } - - @Override - public String serverAgent() { - return serverAgent; - } - - @Override - public BoltServerAddress serverAddress() { - return serverAddress; - } - - @Override - public BoltProtocol protocol() { - return protocol; - } - - @Override - public CompletionStage forceClose(String reason) { - var fut = new CompletableFuture(); - eventLoop().execute(() -> { - setTerminationReason(channel, reason); - channel.close().addListener((ChannelFutureListener) future -> { - if (future.isSuccess()) { - fut.complete(null); - } else { - var cause = future.cause(); - if (cause == null) { - cause = new IllegalStateException("Unexpected state"); - } - fut.completeExceptionally(cause); - } - }); - }); - return fut; - } - - @Override - public CompletionStage close() { - var closeFuture = new CompletableFuture(); - writeMessageInEventLoop(GoodbyeMessage.GOODBYE, new NoOpResponseHandler()) - .thenCompose(ignored -> flush()) - .whenComplete((ignored, throwable) -> { - if (throwable == null) { - this.channel.close().addListener((ChannelFutureListener) future -> { - if (future.isSuccess()) { - closeFuture.complete(null); - } else { - closeFuture.completeExceptionally(future.cause()); - } - }); - } else { - closeFuture.completeExceptionally(throwable); - } - }); - return closeFuture; - } - - @Override - public EventLoop eventLoop() { - return channel.eventLoop(); - } - - @Override - public Optional defaultReadTimeoutMillis() { - return Optional.ofNullable(defaultReadTimeout); - } - - @Override - public void setReadTimeout(Duration duration) { - if (!channel.eventLoop().inEventLoop()) { - throw new IllegalStateException("This method may only be called in the EventLoop"); - } - - if (duration != null && duration.toMillis() > 0) { - // only values greater than zero milliseconds are supported - this.readTimeout = duration; - } else { - this.readTimeout = this.defaultReadTimeout; - } - } - - private CompletionStage writeMessageInEventLoop(Message message, ResponseHandler handler) { - var future = new CompletableFuture(); - Runnable runnable = () -> { - if (messageDispatcher.fatalErrorOccurred() && GoodbyeMessage.GOODBYE.equals(message)) { - future.complete(null); - handler.onSuccess(Collections.emptyMap()); - channel.close(); - return; - } - messageDispatcher.enqueue(handler); - channel.write(message).addListener(writeFuture -> { - if (writeFuture.isSuccess()) { - registerConnectionReadTimeout(channel); - } else { - future.completeExceptionally(writeFuture.cause()); - } - }); - future.complete(null); - }; - if (channel.eventLoop().inEventLoop()) { - runnable.run(); - } else { - channel.eventLoop().execute(runnable); - } - return future; - } - - private void setAutoRead(boolean value) { - channel.config().setAutoRead(value); - } - - private void registerConnectionReadTimeout(Channel channel) { - if (!channel.eventLoop().inEventLoop()) { - throw new IllegalStateException("This method may only be called in the EventLoop"); - } - - if (this.readTimeout != null && connectionReadTimeoutHandler == null) { - connectionReadTimeoutHandler = - new ConnectionReadTimeoutHandler(readTimeout.toMillis(), TimeUnit.MILLISECONDS); - channel.pipeline().addFirst(connectionReadTimeoutHandler); - log.log(System.Logger.Level.DEBUG, "Added ConnectionReadTimeoutHandler"); - messageDispatcher.setBeforeLastHandlerHook(() -> { - channel.pipeline().remove(connectionReadTimeoutHandler); - connectionReadTimeoutHandler = null; - messageDispatcher.setBeforeLastHandlerHook(null); - log.log(System.Logger.Level.DEBUG, "Removed ConnectionReadTimeoutHandler"); - }); - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/AuthorizationStateListener.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/AuthorizationStateListener.java deleted file mode 100644 index 004779ffa4..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/AuthorizationStateListener.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -/** - * Listener for authorization info state maintained on the server side. - */ -public interface AuthorizationStateListener { - /** - * Notifies the listener that the credentials stored on the server side have expired. - */ - void onExpired(); -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/BoltProtocolMinorVersionRange.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/BoltProtocolMinorVersionRange.java deleted file mode 100644 index 7037028ef3..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/BoltProtocolMinorVersionRange.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; - -record BoltProtocolMinorVersionRange(int majorVersion, int minorVersion, int minorVersionNum) { - public boolean contains(BoltProtocolVersion version) { - if (majorVersion != version.getMajorVersion()) { - return false; - } - - return version.getMinorVersion() <= minorVersion && version.getMinorVersion() >= minorVersion - minorVersionNum; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/BoltProtocolUtil.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/BoltProtocolUtil.java deleted file mode 100644 index 08d9730322..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/BoltProtocolUtil.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import static io.netty.buffer.Unpooled.copyInt; -import static io.netty.buffer.Unpooled.unreleasableBuffer; -import static java.lang.Integer.toHexString; - -import io.netty.buffer.ByteBuf; -import java.util.Collections; -import java.util.Comparator; -import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3.BoltProtocolV3; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v42.BoltProtocolV42; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v43.BoltProtocolV43; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v44.BoltProtocolV44; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v5.BoltProtocolV5; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v51.BoltProtocolV51; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v52.BoltProtocolV52; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v53.BoltProtocolV53; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v54.BoltProtocolV54; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v55.BoltProtocolV55; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v56.BoltProtocolV56; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v57.BoltProtocolV57; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v58.BoltProtocolV58; - -public final class BoltProtocolUtil { - public static final int BOLT_MAGIC_PREAMBLE = 0x6060B017; - public static final BoltProtocolVersion NO_PROTOCOL_VERSION = new BoltProtocolVersion(0, 0); - - public static final int CHUNK_HEADER_SIZE_BYTES = 2; - - public static final int DEFAULT_MAX_OUTBOUND_CHUNK_SIZE_BYTES = Short.MAX_VALUE / 2; - - public static final SortedMap versionToProtocol; - - private static final ByteBuf HANDSHAKE_BUF = unreleasableBuffer(copyInt( - BOLT_MAGIC_PREAMBLE, - 0x000001FF, - BoltProtocolV58.VERSION.toIntRange(BoltProtocolV5.VERSION), - BoltProtocolV44.VERSION.toIntRange(BoltProtocolV42.VERSION), - BoltProtocolV3.VERSION.toInt())) - .asReadOnly(); - - private static final String HANDSHAKE_STRING = createHandshakeString(); - - static { - var map = new TreeMap(Comparator.reverseOrder()); - map.putAll(Map.ofEntries( - Map.entry(BoltProtocolV58.VERSION, BoltProtocolV58.INSTANCE), - Map.entry(BoltProtocolV57.VERSION, BoltProtocolV57.INSTANCE), - Map.entry(BoltProtocolV56.VERSION, BoltProtocolV56.INSTANCE), - Map.entry(BoltProtocolV55.VERSION, BoltProtocolV55.INSTANCE), - Map.entry(BoltProtocolV54.VERSION, BoltProtocolV54.INSTANCE), - Map.entry(BoltProtocolV53.VERSION, BoltProtocolV53.INSTANCE), - Map.entry(BoltProtocolV52.VERSION, BoltProtocolV52.INSTANCE), - Map.entry(BoltProtocolV51.VERSION, BoltProtocolV51.INSTANCE), - Map.entry(BoltProtocolV5.VERSION, BoltProtocolV5.INSTANCE), - Map.entry(BoltProtocolV44.VERSION, BoltProtocolV44.INSTANCE), - Map.entry(BoltProtocolV43.VERSION, BoltProtocolV43.INSTANCE), - Map.entry(BoltProtocolV42.VERSION, BoltProtocolV42.INSTANCE), - Map.entry(BoltProtocolV3.VERSION, BoltProtocolV3.INSTANCE))); - versionToProtocol = Collections.unmodifiableSortedMap(map); - } - - private BoltProtocolUtil() {} - - public static ByteBuf handshakeBuf() { - return HANDSHAKE_BUF.duplicate(); - } - - public static String handshakeString() { - return HANDSHAKE_STRING; - } - - public static void writeMessageBoundary(ByteBuf buf) { - buf.writeShort(0); - } - - public static void writeEmptyChunkHeader(ByteBuf buf) { - buf.writeShort(0); - } - - public static void writeChunkHeader(ByteBuf buf, int chunkStartIndex, int headerValue) { - buf.setShort(chunkStartIndex, headerValue); - } - - private static String createHandshakeString() { - var buf = handshakeBuf(); - return String.format( - "[0x%s, %s, %s, %s, %s]", - toHexString(buf.readInt()), buf.readInt(), buf.readInt(), buf.readInt(), buf.readInt()); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelAttributes.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelAttributes.java deleted file mode 100644 index c91af9d337..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelAttributes.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import static io.netty.util.AttributeKey.valueOf; - -import io.netty.channel.Channel; -import io.netty.util.AttributeKey; -import java.util.Collections; -import java.util.HashSet; -import java.util.Optional; -import java.util.Set; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltPatchesListener; - -public final class ChannelAttributes { - private static final AttributeKey CONNECTION_ID = valueOf("connectionId"); - private static final AttributeKey PROTOCOL_VERSION = valueOf("protocolVersion"); - private static final AttributeKey SERVER_AGENT = valueOf("serverAgent"); - private static final AttributeKey ADDRESS = valueOf("serverAddress"); - private static final AttributeKey CREATION_TIMESTAMP = valueOf("creationTimestamp"); - private static final AttributeKey LAST_USED_TIMESTAMP = valueOf("lastUsedTimestamp"); - private static final AttributeKey MESSAGE_DISPATCHER = valueOf("messageDispatcher"); - private static final AttributeKey TERMINATION_REASON = valueOf("terminationReason"); - private static final AttributeKey AUTHORIZATION_STATE_LISTENER = - valueOf("authorizationStateListener"); - private static final AttributeKey> BOLT_PATCHES_LISTENERS = - valueOf("boltPatchesListeners"); - - // configuration hints provided by the server - private static final AttributeKey CONNECTION_READ_TIMEOUT = valueOf("connectionReadTimeout"); - private static final AttributeKey TELEMETRY_ENABLED = valueOf("telemetryEnabled"); - private static final AttributeKey SSR_ENABLED = valueOf("ssr.enabled"); - - private ChannelAttributes() {} - - public static String connectionId(Channel channel) { - return get(channel, CONNECTION_ID); - } - - public static void setConnectionId(Channel channel, String id) { - setOnce(channel, CONNECTION_ID, id); - } - - public static BoltProtocolVersion protocolVersion(Channel channel) { - return get(channel, PROTOCOL_VERSION); - } - - public static void setProtocolVersion(Channel channel, BoltProtocolVersion version) { - setOnce(channel, PROTOCOL_VERSION, version); - } - - public static void setServerAgent(Channel channel, String serverAgent) { - setOnce(channel, SERVER_AGENT, serverAgent); - } - - public static String serverAgent(Channel channel) { - return get(channel, SERVER_AGENT); - } - - public static BoltServerAddress serverAddress(Channel channel) { - return get(channel, ADDRESS); - } - - public static void setServerAddress(Channel channel, BoltServerAddress address) { - setOnce(channel, ADDRESS, address); - } - - public static long creationTimestamp(Channel channel) { - return get(channel, CREATION_TIMESTAMP); - } - - public static void setCreationTimestamp(Channel channel, long creationTimestamp) { - setOnce(channel, CREATION_TIMESTAMP, creationTimestamp); - } - - public static Long lastUsedTimestamp(Channel channel) { - return get(channel, LAST_USED_TIMESTAMP); - } - - public static void setLastUsedTimestamp(Channel channel, long lastUsedTimestamp) { - set(channel, LAST_USED_TIMESTAMP, lastUsedTimestamp); - } - - public static InboundMessageDispatcher messageDispatcher(Channel channel) { - return get(channel, MESSAGE_DISPATCHER); - } - - public static void setMessageDispatcher(Channel channel, InboundMessageDispatcher messageDispatcher) { - setOnce(channel, MESSAGE_DISPATCHER, messageDispatcher); - } - - public static String terminationReason(Channel channel) { - return get(channel, TERMINATION_REASON); - } - - public static void setTerminationReason(Channel channel, String reason) { - setOnce(channel, TERMINATION_REASON, reason); - } - - public static AuthorizationStateListener authorizationStateListener(Channel channel) { - return get(channel, AUTHORIZATION_STATE_LISTENER); - } - - public static void setAuthorizationStateListener( - Channel channel, AuthorizationStateListener authorizationStateListener) { - set(channel, AUTHORIZATION_STATE_LISTENER, authorizationStateListener); - } - - public static Optional connectionReadTimeout(Channel channel) { - return Optional.ofNullable(get(channel, CONNECTION_READ_TIMEOUT)); - } - - public static void setConnectionReadTimeout(Channel channel, Long connectionReadTimeout) { - setOnce(channel, CONNECTION_READ_TIMEOUT, connectionReadTimeout); - } - - public static void addBoltPatchesListener(Channel channel, BoltPatchesListener listener) { - var boltPatchesListeners = get(channel, BOLT_PATCHES_LISTENERS); - if (boltPatchesListeners == null) { - boltPatchesListeners = new HashSet<>(); - setOnce(channel, BOLT_PATCHES_LISTENERS, boltPatchesListeners); - } - boltPatchesListeners.add(listener); - } - - public static Set boltPatchesListeners(Channel channel) { - var boltPatchesListeners = get(channel, BOLT_PATCHES_LISTENERS); - return boltPatchesListeners != null ? boltPatchesListeners : Collections.emptySet(); - } - - public static void setTelemetryEnabled(Channel channel, Boolean telemetryEnabled) { - setOnce(channel, TELEMETRY_ENABLED, telemetryEnabled); - } - - public static boolean telemetryEnabled(Channel channel) { - return Optional.ofNullable(get(channel, TELEMETRY_ENABLED)).orElse(false); - } - - public static void setSsrEnabled(Channel channel, Boolean telemetryEnabled) { - setOnce(channel, SSR_ENABLED, telemetryEnabled); - } - - public static boolean ssrEnabled(Channel channel) { - return Optional.ofNullable(get(channel, SSR_ENABLED)).orElse(false); - } - - private static T get(Channel channel, AttributeKey key) { - return channel.attr(key).get(); - } - - private static void set(Channel channel, AttributeKey key, T value) { - channel.attr(key).set(value); - } - - private static void setOnce(Channel channel, AttributeKey key, T value) { - var existingValue = channel.attr(key).setIfAbsent(value); - if (existingValue != null) { - throw new IllegalStateException( - "Unable to set " + key.name() + " because it is already set to " + existingValue); - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelConnectedListener.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelConnectedListener.java deleted file mode 100644 index 7359f9b1d5..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelConnectedListener.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import static java.lang.String.format; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.BoltProtocolUtil.handshakeString; - -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import java.util.Objects; -import java.util.concurrent.CompletableFuture; -import javax.net.ssl.SSLHandshakeException; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.exception.BoltServiceUnavailableException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.logging.ChannelActivityLogger; - -public class ChannelConnectedListener implements ChannelFutureListener { - private final BoltServerAddress address; - private final ChannelPipelineBuilder pipelineBuilder; - private final CompletableFuture handshakeCompletedFuture; - private final LoggingProvider logging; - private final ValueFactory valueFactory; - - public ChannelConnectedListener( - BoltServerAddress address, - ChannelPipelineBuilder pipelineBuilder, - CompletableFuture handshakeCompletedFuture, - LoggingProvider logging, - ValueFactory valueFactory) { - this.address = address; - this.pipelineBuilder = pipelineBuilder; - this.handshakeCompletedFuture = handshakeCompletedFuture; - this.logging = logging; - this.valueFactory = Objects.requireNonNull(valueFactory); - } - - @Override - public void operationComplete(ChannelFuture future) { - if (future.isSuccess()) { - var channel = future.channel(); - var log = new ChannelActivityLogger(channel, logging, getClass()); - log.log(System.Logger.Level.TRACE, "Channel %s connected, initiating bolt handshake", channel); - - var pipeline = channel.pipeline(); - pipeline.addLast(new HandshakeHandler(pipelineBuilder, handshakeCompletedFuture, logging, valueFactory)); - log.log(System.Logger.Level.DEBUG, "C: [Bolt Handshake] %s", handshakeString()); - channel.writeAndFlush(BoltProtocolUtil.handshakeBuf()).addListener(f -> { - if (!f.isSuccess()) { - var error = f.cause(); - if (!(error instanceof SSLHandshakeException)) { - error = new BoltServiceUnavailableException( - String.format("Unable to write Bolt handshake to %s.", this.address), error); - } - this.handshakeCompletedFuture.completeExceptionally(error); - } - }); - } else { - handshakeCompletedFuture.completeExceptionally(databaseUnavailableError(address, future.cause())); - } - } - - private static Throwable databaseUnavailableError(BoltServerAddress address, Throwable cause) { - return new BoltServiceUnavailableException( - format( - "Unable to connect to %s, ensure the database is running and that there " - + "is a working network connection to it.", - address), - cause); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelPipelineBuilder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelPipelineBuilder.java deleted file mode 100644 index 986905b0be..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelPipelineBuilder.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import io.netty.channel.ChannelPipeline; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; - -public interface ChannelPipelineBuilder { - void build( - MessageFormat messageFormat, ChannelPipeline pipeline, LoggingProvider logging, ValueFactory valueFactory); -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelPipelineBuilderImpl.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelPipelineBuilderImpl.java deleted file mode 100644 index cce79c4ae9..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelPipelineBuilderImpl.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.addBoltPatchesListener; - -import io.netty.channel.ChannelPipeline; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.ChannelErrorHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.ChunkDecoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.MessageDecoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.outbound.OutboundMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; - -public class ChannelPipelineBuilderImpl implements ChannelPipelineBuilder { - @Override - public void build( - MessageFormat messageFormat, ChannelPipeline pipeline, LoggingProvider logging, ValueFactory valueFactory) { - // inbound handlers - pipeline.addLast(new ChunkDecoder(logging)); - pipeline.addLast(new MessageDecoder()); - var channel = pipeline.channel(); - var inboundMessageHandler = new InboundMessageHandler(messageFormat, logging, valueFactory); - addBoltPatchesListener(channel, inboundMessageHandler); - pipeline.addLast(inboundMessageHandler); - - // outbound handlers - var outboundMessageHandler = new OutboundMessageHandler(messageFormat, logging, valueFactory); - addBoltPatchesListener(channel, outboundMessageHandler); - pipeline.addLast(OutboundMessageHandler.NAME, outboundMessageHandler); - - // last one - error handler - pipeline.addLast(new ChannelErrorHandler(logging)); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/EventLoopGroupFactory.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/EventLoopGroupFactory.java deleted file mode 100644 index e72dc078af..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/EventLoopGroupFactory.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.util.concurrent.DefaultThreadFactory; -import io.netty.util.concurrent.FastThreadLocalThread; -import java.util.concurrent.Executor; -import java.util.concurrent.ThreadFactory; -import org.neo4j.driver.internal.bolt.basicimpl.EventLoopThread; - -/** - * Manages creation of Netty {@link EventLoopGroup}s, which are basically {@link Executor}s that perform IO operations. - */ -public final class EventLoopGroupFactory { - private static final String THREAD_NAME_PREFIX = "Neo4jDriverIO"; - private static final int THREAD_PRIORITY = Thread.MAX_PRIORITY; - private static final boolean THREAD_IS_DAEMON = true; - - private EventLoopGroupFactory() {} - - /** - * Get class of {@link Channel} for {@link Bootstrap#channel(Class)} method. - * - * @return class of the channel, which should be consistent with {@link EventLoopGroup}s returned by - * {@link #newEventLoopGroup(int)}. - */ - public static Class channelClass() { - return NioSocketChannel.class; - } - - /** - * Create new {@link EventLoopGroup} with specified thread count. Returned group should by given to - * {@link Bootstrap#group(EventLoopGroup)}. - * - * @param threadCount amount of IO threads for the new group. - * @return new group consistent with channel class returned by {@link #channelClass()}. - */ - public static EventLoopGroup newEventLoopGroup(int threadCount) { - return new DriverEventLoopGroup(threadCount); - } - - /** - * Assert that current thread is not an event loop used for async IO operations. This check is needed because - * blocking API methods are implemented on top of corresponding async API methods. Deadlocks might happen when - * IO thread executes blocking API call and has to wait for itself to read from the network. - * - * @throws IllegalStateException when current thread is an event loop IO thread. - */ - public static void assertNotInEventLoopThread() throws IllegalStateException { - if (isEventLoopThread(Thread.currentThread())) { - throw new IllegalStateException( - "Blocking operation can't be executed in IO thread because it might result in a deadlock. " - + "Please do not use blocking API when chaining futures returned by async API methods."); - } - } - - /** - * Check if given thread is an event loop IO thread. - * - * @param thread the thread to check. - * @return {@code true} when given thread belongs to the event loop, {@code false} otherwise. - */ - public static boolean isEventLoopThread(Thread thread) { - return thread instanceof EventLoopThread; - } - - /** - * Same as {@link NioEventLoopGroup} but uses a different {@link ThreadFactory} that produces threads of - * {@link EventLoopThread} class. Such threads can be recognized by {@link #assertNotInEventLoopThread()}. - */ - private static class DriverEventLoopGroup extends NioEventLoopGroup { - DriverEventLoopGroup(int nThreads) { - super(nThreads); - } - - @Override - protected ThreadFactory newDefaultThreadFactory() { - return new DriverThreadFactory(); - } - } - - /** - * Same as {@link DefaultThreadFactory} created by {@link NioEventLoopGroup} by default, except produces threads of - * {@link DriverThread} class. Such threads can be recognized by {@link #assertNotInEventLoopThread()}. - */ - private static class DriverThreadFactory extends DefaultThreadFactory { - DriverThreadFactory() { - super(THREAD_NAME_PREFIX, THREAD_IS_DAEMON, THREAD_PRIORITY); - } - - @SuppressWarnings("InstantiatingAThreadWithDefaultRunMethod") - @Override - protected Thread newThread(Runnable r, String name) { - return new DriverThread(threadGroup, r, name); - } - } - - /** - * Same as default thread created by {@link DefaultThreadFactory} except this dedicated class can be easily - * recognized by {@link #assertNotInEventLoopThread()}. - */ - private static class DriverThread extends FastThreadLocalThread implements EventLoopThread { - DriverThread(ThreadGroup group, Runnable target, String name) { - super(group, target, name); - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/HandshakeHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/HandshakeHandler.java deleted file mode 100644 index a2fa5d4217..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/HandshakeHandler.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import static org.neo4j.driver.internal.bolt.api.BoltProtocolVersion.isHttp; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.DecoderException; -import io.netty.handler.codec.ReplayingDecoder; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.CompletableFuture; -import javax.net.ssl.SSLHandshakeException; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.exception.BoltClientException; -import org.neo4j.driver.internal.bolt.api.exception.BoltServiceUnavailableException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.logging.ChannelActivityLogger; -import org.neo4j.driver.internal.bolt.basicimpl.impl.logging.ChannelErrorLogger; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; - -public class HandshakeHandler extends ReplayingDecoder { - private final ChannelPipelineBuilder pipelineBuilder; - private final CompletableFuture handshakeCompletedFuture; - private final LoggingProvider logging; - private final ValueFactory valueFactory; - - private boolean failed; - private ChannelActivityLogger log; - private ChannelErrorLogger errorLog; - private ManifestHandler manifestHandler; - - public HandshakeHandler( - ChannelPipelineBuilder pipelineBuilder, - CompletableFuture handshakeCompletedFuture, - LoggingProvider logging, - ValueFactory valueFactory) { - this.pipelineBuilder = pipelineBuilder; - this.handshakeCompletedFuture = handshakeCompletedFuture; - this.logging = logging; - this.valueFactory = Objects.requireNonNull(valueFactory); - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) { - log = new ChannelActivityLogger(ctx.channel(), logging, getClass()); - errorLog = new ChannelErrorLogger(ctx.channel(), logging); - } - - @Override - protected void handlerRemoved0(ChannelHandlerContext ctx) { - failed = false; - log = null; - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) { - log.log(System.Logger.Level.DEBUG, "Channel is inactive"); - - if (!failed) { - // channel became inactive while doing bolt handshake, not because of some previous error - var error = newConnectionTerminatedError(); - fail(ctx, error); - } - } - - public static BoltServiceUnavailableException newConnectionTerminatedError() { - return new BoltServiceUnavailableException("Connection to the database terminated. " - + "Please ensure that your database is listening on the correct host and port and that you have compatible encryption settings both on Neo4j server and driver. " - + "Note that the default encryption setting has changed in Neo4j 4.0."); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable error) { - if (failed) { - errorLog.traceOrDebug("Another fatal error occurred in the pipeline", error); - } else { - failed = true; - var cause = transformError(error); - fail(ctx, cause); - } - } - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) { - if (manifestHandler != null) { - try { - manifestHandler.decode(in); - } catch (Throwable e) { - fail(ctx, e); - } - } else { - var serverSuggestedVersion = BoltProtocolVersion.fromRawBytes(in.readInt()); - - if (new BoltProtocolVersion(255, 1).equals(serverSuggestedVersion)) { - log.log(System.Logger.Level.DEBUG, "S: [Bolt Handshake Manifest] v1", serverSuggestedVersion); - manifestHandler = new ManifestHandlerV1(ctx.channel(), logging); - } else { - log.log(System.Logger.Level.DEBUG, "S: [Bolt Handshake] %s", serverSuggestedVersion); - - // this is a one-time handler, remove it when protocol version has been read - ctx.pipeline().remove(this); - - var protocol = protocolForVersion(serverSuggestedVersion); - if (protocol != null) { - protocolSelected(serverSuggestedVersion, protocol.createMessageFormat(), ctx); - } else { - handleUnknownSuggestedProtocolVersion(serverSuggestedVersion, ctx); - } - } - } - } - - @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { - if (manifestHandler != null) { - // this is a one-time handler, remove it when protocol version has been read - ctx.pipeline().remove(this); - try { - var protocol = manifestHandler.complete(); - protocolSelected(protocol.version(), protocol.createMessageFormat(), ctx); - } catch (Throwable e) { - fail(ctx, e); - } - } - super.channelReadComplete(ctx); - } - - private BoltProtocol protocolForVersion(BoltProtocolVersion version) { - try { - return BoltProtocol.forVersion(version); - } catch (BoltClientException e) { - return null; - } - } - - private void protocolSelected(BoltProtocolVersion version, MessageFormat messageFormat, ChannelHandlerContext ctx) { - ChannelAttributes.setProtocolVersion(ctx.channel(), version); - pipelineBuilder.build(messageFormat, ctx.pipeline(), logging, valueFactory); - handshakeCompletedFuture.complete(ctx.channel()); - } - - private void handleUnknownSuggestedProtocolVersion(BoltProtocolVersion version, ChannelHandlerContext ctx) { - if (BoltProtocolUtil.NO_PROTOCOL_VERSION.equals(version)) { - fail(ctx, protocolNoSupportedByServerError()); - } else if (isHttp(version)) { - fail(ctx, httpEndpointError()); - } else { - fail(ctx, protocolNoSupportedByDriverError(version)); - } - } - - private void fail(ChannelHandlerContext ctx, Throwable error) { - ctx.close().addListener(future -> handshakeCompletedFuture.completeExceptionally(error)); - } - - private static Throwable protocolNoSupportedByServerError() { - return new BoltClientException("The server does not support any of the protocol versions supported by " - + "this driver. Ensure that you are using driver and server versions that " - + "are compatible with one another."); - } - - private static Throwable httpEndpointError() { - return new BoltClientException( - "Server responded HTTP. Make sure you are not trying to connect to the http endpoint " - + "(HTTP defaults to port 7474 whereas BOLT defaults to port 7687)"); - } - - private static Throwable protocolNoSupportedByDriverError(BoltProtocolVersion suggestedProtocolVersion) { - return new BoltClientException( - "Protocol error, server suggested unexpected protocol version: " + suggestedProtocolVersion); - } - - private static Throwable transformError(Throwable error) { - if (error instanceof DecoderException && error.getCause() != null) { - // unwrap the DecoderException if it has a cause - error = error.getCause(); - } - - if (error instanceof BoltServiceUnavailableException || error instanceof SSLHandshakeException) { - return error; - } else { - return new BoltServiceUnavailableException("Failed to establish connection with the server", error); - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ManifestHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ManifestHandler.java deleted file mode 100644 index 6a69baf2c8..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ManifestHandler.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import io.netty.buffer.ByteBuf; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; - -interface ManifestHandler { - void decode(ByteBuf in); - - BoltProtocol complete(); -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ManifestHandlerV1.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ManifestHandlerV1.java deleted file mode 100644 index 9fa2d0bc42..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ManifestHandlerV1.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import static io.netty.buffer.Unpooled.unreleasableBuffer; -import static java.lang.Integer.toHexString; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.exception.BoltClientException; -import org.neo4j.driver.internal.bolt.basicimpl.impl.logging.ChannelActivityLogger; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; - -final class ManifestHandlerV1 implements ManifestHandler { - private final ChannelActivityLogger log; - private final Channel channel; - private final VarLongBuilder expectedVersionRangesBuilder = new VarLongBuilder(); - - private long expectedVersionRanges = -1L; - private Set serverSupportedVersionRanges; - - public ManifestHandlerV1(Channel channel, LoggingProvider logging) { - this.channel = Objects.requireNonNull(channel); - log = new ChannelActivityLogger(channel, logging, getClass()); - } - - @Override - public void decode(ByteBuf byteBuf) { - if (expectedVersionRanges < 0) { - decodeExpectedVersionsSegment(byteBuf); - } else if (expectedVersionRanges > 0) { - decodeServerSupportedBoltVersionRange(byteBuf); - } else { - byteBuf.readByte(); - } - } - - @Override - public BoltProtocol complete() { - return findSupportedBoltProtocol(); - } - - private void decodeExpectedVersionsSegment(ByteBuf byteBuf) { - var segment = byteBuf.readByte(); - var value = (byte) (0b01111111 & segment); - - try { - expectedVersionRangesBuilder.add(value); - } catch (IllegalStateException e) { - throw new BoltClientException( - "The driver does not support the number of Bolt Protocol version ranges that the server wants to send", - e); - } - - var finished = (segment >> 7) == 0; - if (finished) { - expectedVersionRanges = expectedVersionRangesBuilder.build(); - var size = (int) expectedVersionRanges; - if (expectedVersionRanges != size) { - throw new BoltClientException( - "The driver does not support the number of Bolt Protocol version ranges that the server wants to send"); - } else { - log.log( - System.Logger.Level.DEBUG, - "S: [Bolt Handshake Manifest] [expected version ranges %d]", - expectedVersionRanges); - serverSupportedVersionRanges = new HashSet<>(size); - } - } - } - - private void decodeServerSupportedBoltVersionRange(ByteBuf byteBuf) { - var value = byteBuf.readInt(); - var major = value & 0x000000FF; - var minor = (value >> 8) & 0x000000FF; - var minorNum = (value >> 16) & 0x000000FF; - serverSupportedVersionRanges.add(new BoltProtocolMinorVersionRange(major, minor, minorNum)); - expectedVersionRanges--; - - if (expectedVersionRanges == 0) { - log.log( - System.Logger.Level.DEBUG, - "S: [Bolt Handshake Manifest] [server supported version ranges %s]", - serverSupportedVersionRanges); - } - } - - private BoltProtocol findSupportedBoltProtocol() { - for (var entry : BoltProtocolUtil.versionToProtocol.entrySet()) { - var version = entry.getKey(); - for (var range : serverSupportedVersionRanges) { - if (range.contains(version)) { - var protocol = entry.getValue(); - write(protocol.version().toInt()); - write((byte) 0); - return protocol; - } - } - } - write(0); - write((byte) 0); - channel.flush(); - throw new BoltClientException("No supported Bolt Protocol version was found"); - } - - private void write(int value) { - log.log( - System.Logger.Level.DEBUG, - "C: [Bolt Handshake Manifest] %s", - String.format("[%s]", toHexString(value))); - channel.write(Unpooled.copyInt(value).asReadOnly()); - } - - @SuppressWarnings("SameParameterValue") - private void write(byte value) { - log.log( - System.Logger.Level.DEBUG, - "C: [Bolt Handshake Manifest] %s", - String.format("[%s]", toHexString(value))); - channel.write( - unreleasableBuffer(Unpooled.copiedBuffer(new byte[] {value})).asReadOnly()); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/NettyChannelInitializer.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/NettyChannelInitializer.java deleted file mode 100644 index 2f36b1da87..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/NettyChannelInitializer.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import io.netty.channel.Channel; -import io.netty.channel.ChannelInitializer; -import io.netty.handler.ssl.SslHandler; -import java.time.Clock; -import javax.net.ssl.SSLEngine; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; - -public class NettyChannelInitializer extends ChannelInitializer { - private final BoltServerAddress address; - private final SecurityPlan securityPlan; - private final int connectTimeoutMillis; - private final Clock clock; - private final LoggingProvider logging; - - public NettyChannelInitializer( - BoltServerAddress address, - SecurityPlan securityPlan, - int connectTimeoutMillis, - Clock clock, - LoggingProvider logging) { - this.address = address; - this.securityPlan = securityPlan; - this.connectTimeoutMillis = connectTimeoutMillis; - this.clock = clock; - this.logging = logging; - } - - @Override - protected void initChannel(Channel channel) { - if (securityPlan.requiresEncryption()) { - var sslHandler = createSslHandler(); - channel.pipeline().addFirst(sslHandler); - } - - updateChannelAttributes(channel); - } - - private SslHandler createSslHandler() { - var sslEngine = createSslEngine(); - var sslHandler = new SslHandler(sslEngine); - sslHandler.setHandshakeTimeoutMillis(connectTimeoutMillis); - return sslHandler; - } - - private SSLEngine createSslEngine() { - var sslContext = securityPlan.sslContext(); - var sslEngine = sslContext.createSSLEngine(address.host(), address.port()); - sslEngine.setNeedClientAuth(securityPlan.requiresClientAuth()); - sslEngine.setUseClientMode(true); - if (securityPlan.requiresHostnameVerification()) { - var sslParameters = sslEngine.getSSLParameters(); - sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); - sslEngine.setSSLParameters(sslParameters); - } - return sslEngine; - } - - private void updateChannelAttributes(Channel channel) { - ChannelAttributes.setServerAddress(channel, address); - ChannelAttributes.setCreationTimestamp(channel, clock.millis()); - ChannelAttributes.setMessageDispatcher(channel, new InboundMessageDispatcher(channel, logging)); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/NettyDomainNameResolver.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/NettyDomainNameResolver.java deleted file mode 100644 index 445641b3c9..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/NettyDomainNameResolver.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import io.netty.resolver.InetNameResolver; -import io.netty.util.concurrent.EventExecutor; -import io.netty.util.concurrent.Promise; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Arrays; -import java.util.List; -import org.neo4j.driver.internal.bolt.api.DomainNameResolver; - -public class NettyDomainNameResolver extends InetNameResolver { - private final DomainNameResolver domainNameResolver; - - public NettyDomainNameResolver(EventExecutor executor, DomainNameResolver domainNameResolver) { - super(executor); - this.domainNameResolver = domainNameResolver; - } - - @Override - protected void doResolve(String inetHost, Promise promise) { - try { - promise.setSuccess(domainNameResolver.resolve(inetHost)[0]); - } catch (UnknownHostException e) { - promise.setFailure(e); - } - } - - @Override - protected void doResolveAll(String inetHost, Promise> promise) { - try { - promise.setSuccess(Arrays.asList(domainNameResolver.resolve(inetHost))); - } catch (UnknownHostException e) { - promise.setFailure(e); - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/NettyDomainNameResolverGroup.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/NettyDomainNameResolverGroup.java deleted file mode 100644 index 3e1c970b5c..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/NettyDomainNameResolverGroup.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import io.netty.resolver.AddressResolver; -import io.netty.resolver.AddressResolverGroup; -import io.netty.util.concurrent.EventExecutor; -import java.net.InetSocketAddress; -import org.neo4j.driver.internal.bolt.api.DomainNameResolver; - -public class NettyDomainNameResolverGroup extends AddressResolverGroup { - private final DomainNameResolver domainNameResolver; - - public NettyDomainNameResolverGroup(DomainNameResolver domainNameResolver) { - this.domainNameResolver = domainNameResolver; - } - - @Override - @SuppressWarnings("resource") - protected AddressResolver newResolver(EventExecutor executor) { - return new NettyDomainNameResolver(executor, domainNameResolver).asAddressResolver(); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/VarLongBuilder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/VarLongBuilder.java deleted file mode 100644 index 1c7061c090..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/VarLongBuilder.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -final class VarLongBuilder { - private long value; - private byte position; - - public void add(long segment) { - if (position > 8) { - throw new IllegalStateException("Segment overflow"); - } - segment = segment << (position * 7); - value |= segment; - position++; - } - - public long build() { - return value; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ByteBufInput.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ByteBufInput.java deleted file mode 100644 index 22f8fcb73a..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ByteBufInput.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound; - -import static java.util.Objects.requireNonNull; - -import io.netty.buffer.ByteBuf; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; - -public class ByteBufInput implements PackInput { - private ByteBuf buf; - - public void start(ByteBuf newBuf) { - assertNotStarted(); - buf = requireNonNull(newBuf); - } - - public void stop() { - buf = null; - } - - @Override - public byte readByte() { - return buf.readByte(); - } - - @Override - public short readShort() { - return buf.readShort(); - } - - @Override - public int readInt() { - return buf.readInt(); - } - - @Override - public long readLong() { - return buf.readLong(); - } - - @Override - public double readDouble() { - return buf.readDouble(); - } - - @Override - public void readBytes(byte[] into, int offset, int toRead) { - buf.readBytes(into, offset, toRead); - } - - @Override - public byte peekByte() { - return buf.getByte(buf.readerIndex()); - } - - private void assertNotStarted() { - if (buf != null) { - throw new IllegalStateException("Already started"); - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ChannelErrorHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ChannelErrorHandler.java deleted file mode 100644 index e23cfae19a..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ChannelErrorHandler.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound; - -import static java.util.Objects.requireNonNull; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.handler.codec.CodecException; -import java.io.IOException; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.exception.BoltConnectionReadTimeoutException; -import org.neo4j.driver.internal.bolt.api.exception.BoltServiceUnavailableException; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; -import org.neo4j.driver.internal.bolt.basicimpl.impl.logging.ChannelActivityLogger; -import org.neo4j.driver.internal.bolt.basicimpl.impl.logging.ChannelErrorLogger; - -public class ChannelErrorHandler extends ChannelInboundHandlerAdapter { - private final LoggingProvider logging; - - private InboundMessageDispatcher messageDispatcher; - private ChannelActivityLogger log; - private ChannelErrorLogger errorLog; - private boolean failed; - - public ChannelErrorHandler(LoggingProvider logging) { - this.logging = logging; - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) { - messageDispatcher = requireNonNull(ChannelAttributes.messageDispatcher(ctx.channel())); - log = new ChannelActivityLogger(ctx.channel(), logging, getClass()); - errorLog = new ChannelErrorLogger(ctx.channel(), logging); - } - - @Override - public void handlerRemoved(ChannelHandlerContext ctx) { - messageDispatcher = null; - log = null; - failed = false; - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) { - log.log(System.Logger.Level.DEBUG, "Channel is inactive"); - - var terminationReason = ChannelAttributes.terminationReason(ctx.channel()); - Throwable error = terminationReason == null - ? new BoltServiceUnavailableException("Connection to the database terminated. " - + "Please ensure that your database is listening on the correct host and port and that you have compatible encryption settings both on Neo4j server and driver. " - + "Note that the default encryption setting has changed in Neo4j 4.0.") - : new BoltServiceUnavailableException("Connection to the database terminated. " + terminationReason); - - if (!failed) { - // channel became inactive not because of a fatal exception that came from exceptionCaught - // it is most likely inactive because actual network connection broke or was explicitly closed by the driver - - messageDispatcher.handleChannelInactive(error); - } else { - fail(error); - } - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable error) { - if (failed) { - errorLog.traceOrDebug("Another fatal error occurred in the pipeline", error); - } else { - failed = true; - logUnexpectedErrorWarning(error); - fail(error); - } - } - - private void logUnexpectedErrorWarning(Throwable error) { - if (!(error instanceof BoltConnectionReadTimeoutException)) { - errorLog.traceOrDebug("Fatal error occurred in the pipeline", error); - } - } - - private void fail(Throwable error) { - var cause = transformError(error); - messageDispatcher.handleChannelError(cause); - } - - private static Throwable transformError(Throwable error) { - if (error instanceof CodecException && error.getCause() != null) { - // unwrap the CodecException if it has a cause - error = error.getCause(); - } - - if (error instanceof IOException) { - return new BoltServiceUnavailableException("Connection to the database failed", error); - } else { - return error; - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ChunkDecoder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ChunkDecoder.java deleted file mode 100644 index d8bf92e4e8..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ChunkDecoder.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.LengthFieldBasedFrameDecoder; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.logging.ChannelActivityLogger; - -public class ChunkDecoder extends LengthFieldBasedFrameDecoder { - private static final int MAX_FRAME_BODY_LENGTH = 0xFFFF; - private static final int LENGTH_FIELD_OFFSET = 0; - private static final int LENGTH_FIELD_LENGTH = 2; - private static final int LENGTH_ADJUSTMENT = 0; - private static final int INITIAL_BYTES_TO_STRIP = LENGTH_FIELD_LENGTH; - private static final int MAX_FRAME_LENGTH = LENGTH_FIELD_LENGTH + MAX_FRAME_BODY_LENGTH; - - private final LoggingProvider logging; - private System.Logger log; - - public ChunkDecoder(LoggingProvider logging) { - super(MAX_FRAME_LENGTH, LENGTH_FIELD_OFFSET, LENGTH_FIELD_LENGTH, LENGTH_ADJUSTMENT, INITIAL_BYTES_TO_STRIP); - this.logging = logging; - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) { - log = new ChannelActivityLogger(ctx.channel(), logging, getClass()); - } - - @Override - protected void handlerRemoved0(ChannelHandlerContext ctx) { - log = null; - } - - @Override - protected ByteBuf extractFrame(ChannelHandlerContext ctx, ByteBuf buffer, int index, int length) { - if (log.isLoggable(System.Logger.Level.TRACE)) { - var originalReaderIndex = buffer.readerIndex(); - var readerIndexWithChunkHeader = originalReaderIndex - INITIAL_BYTES_TO_STRIP; - var lengthWithChunkHeader = INITIAL_BYTES_TO_STRIP + length; - var hexDump = ByteBufUtil.hexDump(buffer, readerIndexWithChunkHeader, lengthWithChunkHeader); - log.log(System.Logger.Level.TRACE, "S: %s", hexDump); - } - return super.extractFrame(ctx, buffer, index, length); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ConnectTimeoutHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ConnectTimeoutHandler.java deleted file mode 100644 index de305ad6ea..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ConnectTimeoutHandler.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.timeout.ReadTimeoutHandler; -import java.util.concurrent.TimeUnit; -import org.neo4j.driver.internal.bolt.api.exception.BoltServiceUnavailableException; - -/** - * Handler needed to limit amount of time connection performs TLS and Bolt handshakes. - * It should only be used when connection is established and removed from the pipeline afterwards. - * Otherwise it will make long running queries fail. - */ -public class ConnectTimeoutHandler extends ReadTimeoutHandler { - private final long timeoutMillis; - private boolean triggered; - - public ConnectTimeoutHandler(long timeoutMillis) { - super(timeoutMillis, TimeUnit.MILLISECONDS); - this.timeoutMillis = timeoutMillis; - } - - @Override - protected void readTimedOut(ChannelHandlerContext ctx) { - if (!triggered) { - triggered = true; - ctx.fireExceptionCaught(unableToConnectError()); - } - } - - private BoltServiceUnavailableException unableToConnectError() { - return new BoltServiceUnavailableException("Unable to establish connection in " + timeoutMillis + "ms"); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ConnectionReadTimeoutHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ConnectionReadTimeoutHandler.java deleted file mode 100644 index 998bf5da82..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ConnectionReadTimeoutHandler.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.timeout.ReadTimeoutHandler; -import java.util.concurrent.TimeUnit; -import org.neo4j.driver.internal.bolt.api.exception.BoltConnectionReadTimeoutException; - -public class ConnectionReadTimeoutHandler extends ReadTimeoutHandler { - private boolean triggered; - - public ConnectionReadTimeoutHandler(long timeout, TimeUnit unit) { - super(timeout, unit); - } - - @Override - protected void readTimedOut(ChannelHandlerContext ctx) { - if (!triggered) { - ctx.fireExceptionCaught( - new BoltConnectionReadTimeoutException( - "Connection read timed out due to it taking longer than the server-supplied timeout value via configuration hint.")); - ctx.close(); - triggered = true; - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/InboundMessageDispatcher.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/InboundMessageDispatcher.java deleted file mode 100644 index cc80334eec..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/InboundMessageDispatcher.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound; - -import static java.util.Objects.requireNonNull; - -import io.netty.channel.Channel; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.Map; -import java.util.Queue; -import org.neo4j.driver.internal.bolt.api.GqlError; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.exception.BoltFailureException; -import org.neo4j.driver.internal.bolt.api.exception.BoltGqlErrorException; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.MessageIgnoredException; -import org.neo4j.driver.internal.bolt.basicimpl.impl.logging.ChannelActivityLogger; -import org.neo4j.driver.internal.bolt.basicimpl.impl.logging.ChannelErrorLogger; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ResponseMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.ResponseHandler; - -public class InboundMessageDispatcher implements ResponseMessageHandler { - private final Channel channel; - private final Queue handlers = new LinkedList<>(); - private final System.Logger log; - private final ChannelErrorLogger errorLog; - - private volatile boolean gracefullyClosed; - private boolean fatalErrorOccurred; - private Runnable beforeLastHandlerHook; - - private ResponseHandler autoReadManagingHandler; - - public InboundMessageDispatcher(Channel channel, LoggingProvider logging) { - this.channel = requireNonNull(channel); - this.log = new ChannelActivityLogger(channel, logging, getClass()); - this.errorLog = new ChannelErrorLogger(channel, logging); - } - - public void enqueue(ResponseHandler handler) { - if (fatalErrorOccurred) { - log.log(System.Logger.Level.INFO, String.format("No handlers are accepted %s", handler.toString())); - handler.onFailure(new IllegalStateException("No handlers are accepted after fatal error")); - } else { - handlers.add(handler); - updateAutoReadManagingHandlerIfNeeded(handler); - } - } - - public void setBeforeLastHandlerHook(Runnable beforeLastHandlerHook) { - if (!channel.eventLoop().inEventLoop()) { - throw new IllegalStateException("This method may only be called in the EventLoop"); - } - this.beforeLastHandlerHook = beforeLastHandlerHook; - } - - public int queuedHandlersCount() { - return handlers.size(); - } - - @Override - public void handleSuccessMessage(Map meta) { - if (log.isLoggable(System.Logger.Level.DEBUG)) { - log.log(System.Logger.Level.DEBUG, "S: SUCCESS %s", meta); - } - invokeBeforeLastHandlerHook(); - var handler = removeHandler(); - handler.onSuccess(meta); - } - - @Override - public void handleRecordMessage(Value[] fields) { - if (log.isLoggable(System.Logger.Level.DEBUG)) { - log.log(System.Logger.Level.DEBUG, "S: RECORD %s", Arrays.toString(fields)); - } - var handler = handlers.peek(); - if (handler == null) { - throw new IllegalStateException( - "No handler exists to handle RECORD message with fields: " + Arrays.toString(fields)); - } - handler.onRecord(fields); - } - - @Override - public void handleFailureMessage(GqlError gqlError) { - if (log.isLoggable(System.Logger.Level.DEBUG)) { - log.log(System.Logger.Level.DEBUG, "S: FAILURE %s \"%s\"", gqlError.code(), gqlError.message()); - } - - var error = map(gqlError); - invokeBeforeLastHandlerHook(); - var handler = removeHandler(); - handler.onFailure(error); - } - - private BoltFailureException map(GqlError error) { - var code = error.code(); - - // Since 5.0 these 2 errors have been moved to ClientError class. - // This mapping is required when driver is connected to earlier server versions. - if ("Neo.TransientError.Transaction.Terminated".equals(code)) { - code = "Neo.ClientError.Transaction.Terminated"; - } else if ("Neo.TransientError.Transaction.LockClientStopped".equals(code)) { - code = "Neo.ClientError.Transaction.LockClientStopped"; - } - - return new BoltFailureException( - code, - error.message(), - error.gqlStatus(), - error.statusDescription(), - error.diagnosticRecord(), - mapNested(error.cause())); - } - - private BoltGqlErrorException mapNested(GqlError error) { - BoltGqlErrorException mapped = null; - if (error != null) { - mapped = new BoltGqlErrorException( - error.message(), - error.gqlStatus(), - error.statusDescription(), - error.diagnosticRecord(), - mapNested(error.cause())); - } - return mapped; - } - - @Override - public void handleIgnoredMessage() { - if (log.isLoggable(System.Logger.Level.DEBUG)) { - log.log(System.Logger.Level.DEBUG, "S: IGNORED"); - } - - invokeBeforeLastHandlerHook(); - var handler = removeHandler(); - handler.onFailure(new MessageIgnoredException("The server has ignored the message")); - } - - public void handleChannelInactive(Throwable cause) { - // report issue if the connection has not been terminated as a result of a graceful shutdown request from its - // parent pool - if (!gracefullyClosed) { - handleChannelError(cause); - } else { - while (!handlers.isEmpty()) { - var handler = removeHandler(); - handler.onFailure(cause); - } - channel.close(); - } - } - - public void handleChannelError(Throwable error) { - this.fatalErrorOccurred = true; - - while (!this.handlers.isEmpty()) { - var handler = removeHandler(); - handler.onFailure(error); - } - - errorLog.traceOrDebug("Closing channel because of a failure", error); - this.channel.close(); - } - - public boolean fatalErrorOccurred() { - return fatalErrorOccurred; - } - - /** - * Visible for testing - */ - ResponseHandler autoReadManagingHandler() { - return autoReadManagingHandler; - } - - private ResponseHandler removeHandler() { - var handler = handlers.remove(); - if (handler == autoReadManagingHandler) { - // the auto-read managing handler is being removed - // make sure this dispatcher does not hold on to a removed handler - updateAutoReadManagingHandler(null); - } - return handler; - } - - private void updateAutoReadManagingHandlerIfNeeded(ResponseHandler handler) { - if (handler.canManageAutoRead()) { - updateAutoReadManagingHandler(handler); - } - } - - private void updateAutoReadManagingHandler(ResponseHandler newHandler) { - if (autoReadManagingHandler != null) { - // there already exists a handler that manages channel's auto-read - // make it stop because new managing handler is being added and there should only be a single such handler - autoReadManagingHandler.disableAutoReadManagement(); - // restore the default value of auto-read - channel.config().setAutoRead(true); - } - autoReadManagingHandler = newHandler; - } - - private void invokeBeforeLastHandlerHook() { - if (handlers.size() == 1 && beforeLastHandlerHook != null) { - beforeLastHandlerHook.run(); - } - } - - // For testing only - System.Logger getLog() { - return log; - } - - // For testing only - System.Logger getErrorLog() { - return errorLog; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/InboundMessageHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/InboundMessageHandler.java deleted file mode 100644 index 7d2e2c80d3..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/InboundMessageHandler.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound; - -import static io.netty.buffer.ByteBufUtil.hexDump; -import static java.util.Objects.requireNonNull; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.handler.codec.DecoderException; -import java.util.Set; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; -import org.neo4j.driver.internal.bolt.basicimpl.impl.logging.ChannelActivityLogger; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltPatchesListener; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; - -public class InboundMessageHandler extends SimpleChannelInboundHandler implements BoltPatchesListener { - private final ByteBufInput input; - private final MessageFormat messageFormat; - private final LoggingProvider logging; - private final ValueFactory valueFactory; - - private InboundMessageDispatcher messageDispatcher; - private MessageFormat.Reader reader; - private System.Logger log; - - public InboundMessageHandler(MessageFormat messageFormat, LoggingProvider logging, ValueFactory valueFactory) { - this.input = new ByteBufInput(); - this.messageFormat = messageFormat; - this.logging = logging; - this.reader = messageFormat.newReader(input, valueFactory); - this.valueFactory = requireNonNull(valueFactory); - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) { - var channel = ctx.channel(); - messageDispatcher = requireNonNull(ChannelAttributes.messageDispatcher(channel)); - log = new ChannelActivityLogger(channel, logging, getClass()); - } - - @Override - public void handlerRemoved(ChannelHandlerContext ctx) { - messageDispatcher = null; - log = null; - } - - @Override - protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) { - if (messageDispatcher.fatalErrorOccurred()) { - log.log( - System.Logger.Level.WARNING, - "Message ignored because of the previous fatal error. Channel will be closed. Message:\n%s", - hexDump(msg)); - return; - } - - if (log.isLoggable(System.Logger.Level.TRACE)) { - log.log(System.Logger.Level.TRACE, "S: %s", hexDump(msg)); - } - - input.start(msg); - try { - reader.read(messageDispatcher); - } catch (Throwable error) { - throw new DecoderException("Failed to read inbound message:\n" + hexDump(msg) + "\n", error); - } finally { - input.stop(); - } - } - - @Override - public void handle(Set patches) { - if (patches.contains(DATE_TIME_UTC_PATCH)) { - messageFormat.enableDateTimeUtc(); - reader = messageFormat.newReader(input, valueFactory); - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/MessageDecoder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/MessageDecoder.java deleted file mode 100644 index 1215878a0c..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/MessageDecoder.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.ByteToMessageDecoder; -import java.util.List; - -public class MessageDecoder extends ByteToMessageDecoder { - private static final Cumulator DEFAULT_CUMULATOR = determineDefaultCumulator(); - - private boolean readMessageBoundary; - - public MessageDecoder() { - setCumulator(DEFAULT_CUMULATOR); - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - if (msg instanceof ByteBuf) { - // on every read check if input buffer is empty or not - // if it is empty then it's a message boundary and full message is in the buffer - readMessageBoundary = ((ByteBuf) msg).readableBytes() == 0; - } - super.channelRead(ctx, msg); - } - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) { - if (readMessageBoundary) { - // now we have a complete message in the input buffer - - // increment ref count of the buffer and create it's duplicate that shares the content - // duplicate will be the output of this decoded and input for the next one - var messageBuf = in.retainedDuplicate(); - - // signal that whole message was read by making input buffer seem like it was fully read/consumed - in.readerIndex(in.readableBytes()); - - // pass the full message to the next handler in the pipeline - out.add(messageBuf); - - readMessageBoundary = false; - } - } - - private static Cumulator determineDefaultCumulator() { - var value = System.getProperty("messageDecoderCumulator", ""); - if ("merge".equals(value)) { - return MERGE_CUMULATOR; - } - return COMPOSITE_CUMULATOR; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/outbound/ChunkAwareByteBufOutput.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/outbound/ChunkAwareByteBufOutput.java deleted file mode 100644 index e722c1539e..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/outbound/ChunkAwareByteBufOutput.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.outbound; - -import static java.util.Objects.requireNonNull; - -import io.netty.buffer.ByteBuf; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.BoltProtocolUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -public class ChunkAwareByteBufOutput implements PackOutput { - private final int maxChunkSize; - - private ByteBuf buf; - private int currentChunkStartIndex; - private int currentChunkSize; - - public ChunkAwareByteBufOutput() { - this(BoltProtocolUtil.DEFAULT_MAX_OUTBOUND_CHUNK_SIZE_BYTES); - } - - ChunkAwareByteBufOutput(int maxChunkSize) { - this.maxChunkSize = verifyMaxChunkSize(maxChunkSize); - } - - public void start(ByteBuf newBuf) { - assertNotStarted(); - buf = requireNonNull(newBuf); - startNewChunk(0); - } - - public void stop() { - writeChunkSizeHeader(); - buf = null; - currentChunkStartIndex = 0; - currentChunkSize = 0; - } - - @Override - public PackOutput writeByte(byte value) { - ensureCanFitInCurrentChunk(1); - buf.writeByte(value); - currentChunkSize += 1; - return this; - } - - @Override - public PackOutput writeBytes(byte[] data) { - var offset = 0; - var length = data.length; - while (offset < length) { - // Ensure there is an open chunk, and that it has at least one byte of space left - ensureCanFitInCurrentChunk(1); - - // Write as much as we can into the current chunk - var amountToWrite = Math.min(availableBytesInCurrentChunk(), length - offset); - - buf.writeBytes(data, offset, amountToWrite); - currentChunkSize += amountToWrite; - offset += amountToWrite; - } - return this; - } - - @Override - public PackOutput writeShort(short value) { - ensureCanFitInCurrentChunk(2); - buf.writeShort(value); - currentChunkSize += 2; - return this; - } - - @Override - public PackOutput writeInt(int value) { - ensureCanFitInCurrentChunk(4); - buf.writeInt(value); - currentChunkSize += 4; - return this; - } - - @Override - public PackOutput writeLong(long value) { - ensureCanFitInCurrentChunk(8); - buf.writeLong(value); - currentChunkSize += 8; - return this; - } - - @Override - public PackOutput writeDouble(double value) { - ensureCanFitInCurrentChunk(8); - buf.writeDouble(value); - currentChunkSize += 8; - return this; - } - - private void ensureCanFitInCurrentChunk(int numberOfBytes) { - var targetChunkSize = currentChunkSize + numberOfBytes; - if (targetChunkSize > maxChunkSize) { - writeChunkSizeHeader(); - startNewChunk(buf.writerIndex()); - } - } - - private void startNewChunk(int index) { - currentChunkStartIndex = index; - BoltProtocolUtil.writeEmptyChunkHeader(buf); - currentChunkSize = BoltProtocolUtil.CHUNK_HEADER_SIZE_BYTES; - } - - private void writeChunkSizeHeader() { - // go to the beginning of the chunk and write the size header - var chunkBodySize = currentChunkSize - BoltProtocolUtil.CHUNK_HEADER_SIZE_BYTES; - BoltProtocolUtil.writeChunkHeader(buf, currentChunkStartIndex, chunkBodySize); - } - - private int availableBytesInCurrentChunk() { - return maxChunkSize - currentChunkSize; - } - - private void assertNotStarted() { - if (buf != null) { - throw new IllegalStateException("Already started"); - } - } - - private static int verifyMaxChunkSize(int maxChunkSize) { - if (maxChunkSize <= 0) { - throw new IllegalArgumentException("Max chunk size should be > 0, given: " + maxChunkSize); - } - return maxChunkSize; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/outbound/OutboundMessageHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/outbound/OutboundMessageHandler.java deleted file mode 100644 index 18cdc37a12..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/outbound/OutboundMessageHandler.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.outbound; - -import static io.netty.buffer.ByteBufUtil.hexDump; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.EncoderException; -import io.netty.handler.codec.MessageToMessageEncoder; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.BoltProtocolUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.logging.ChannelActivityLogger; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltPatchesListener; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; - -public class OutboundMessageHandler extends MessageToMessageEncoder implements BoltPatchesListener { - public static final String NAME = OutboundMessageHandler.class.getSimpleName(); - private final ChunkAwareByteBufOutput output; - private final MessageFormat messageFormat; - private final LoggingProvider logging; - private final ValueFactory valueFactory; - - private MessageFormat.Writer writer; - private System.Logger log; - - public OutboundMessageHandler(MessageFormat messageFormat, LoggingProvider logging, ValueFactory valueFactory) { - this.output = new ChunkAwareByteBufOutput(); - this.messageFormat = messageFormat; - this.logging = logging; - this.writer = messageFormat.newWriter(output, valueFactory); - this.valueFactory = Objects.requireNonNull(valueFactory); - } - - @Override - public void handlerAdded(ChannelHandlerContext ctx) { - log = new ChannelActivityLogger(ctx.channel(), logging, getClass()); - } - - @Override - public void handlerRemoved(ChannelHandlerContext ctx) { - log = null; - } - - @Override - protected void encode(ChannelHandlerContext ctx, Message msg, List out) { - log.log(System.Logger.Level.DEBUG, "C: %s", msg); - - var messageBuf = ctx.alloc().ioBuffer(); - output.start(messageBuf); - try { - writer.write(msg); - output.stop(); - } catch (Throwable error) { - output.stop(); - // release buffer because it will not get added to the out list and no other handler is going to handle it - messageBuf.release(); - throw new EncoderException("Failed to write outbound message: " + msg, error); - } - - if (log.isLoggable(System.Logger.Level.TRACE)) { - log.log(System.Logger.Level.TRACE, "C: %s", hexDump(messageBuf)); - } - - BoltProtocolUtil.writeMessageBoundary(messageBuf); - out.add(messageBuf); - } - - @Override - public void handle(Set patches) { - if (patches.contains(DATE_TIME_UTC_PATCH)) { - messageFormat.enableDateTimeUtc(); - writer = messageFormat.newWriter(output, valueFactory); - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/BeginTxResponseHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/BeginTxResponseHandler.java deleted file mode 100644 index b5332dc454..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/BeginTxResponseHandler.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.handlers; - -import static java.util.Objects.requireNonNull; - -import java.util.Arrays; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.ResponseHandler; - -public class BeginTxResponseHandler implements ResponseHandler { - private final CompletableFuture beginTxFuture; - - public BeginTxResponseHandler(CompletableFuture beginTxFuture) { - this.beginTxFuture = requireNonNull(beginTxFuture); - } - - @Override - public void onSuccess(Map metadata) { - var db = metadata.get("db"); - var databaseName = db != null ? db.asString() : null; - beginTxFuture.complete(new BeginSummaryImpl(databaseName)); - } - - @Override - public void onFailure(Throwable error) { - beginTxFuture.completeExceptionally(error); - } - - @Override - public void onRecord(Value[] fields) { - throw new UnsupportedOperationException( - "Transaction begin is not expected to receive records: " + Arrays.toString(fields)); - } - - private record BeginSummaryImpl(String database) implements BeginSummary { - @Override - public Optional databaseName() { - return Optional.ofNullable(database); - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/CommitTxResponseHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/CommitTxResponseHandler.java deleted file mode 100644 index 09cd51afcd..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/CommitTxResponseHandler.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.handlers; - -import static java.util.Objects.requireNonNull; - -import java.util.Arrays; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import org.neo4j.driver.internal.bolt.api.values.Type; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.ResponseHandler; - -public class CommitTxResponseHandler implements ResponseHandler { - private final CompletableFuture commitFuture; - - public CommitTxResponseHandler(CompletableFuture commitFuture) { - this.commitFuture = requireNonNull(commitFuture); - } - - @Override - public void onSuccess(Map metadata) { - var bookmarkValue = metadata.get("bookmark"); - String bookmark = null; - if (bookmarkValue != null && !bookmarkValue.isNull() && Type.STRING.equals(bookmarkValue.type())) { - bookmark = bookmarkValue.asString(); - if (bookmark.isEmpty()) { - bookmark = null; - } - } - commitFuture.complete(bookmark); - } - - @Override - public void onFailure(Throwable error) { - commitFuture.completeExceptionally(error); - } - - @Override - public void onRecord(Value[] fields) { - throw new UnsupportedOperationException( - "Transaction commit is not expected to receive records: " + Arrays.toString(fields)); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/DiscardResponseHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/DiscardResponseHandler.java deleted file mode 100644 index 71d6886359..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/DiscardResponseHandler.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.handlers; - -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.CompletableFuture; -import org.neo4j.driver.internal.bolt.api.summary.DiscardSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.ResponseHandler; - -public class DiscardResponseHandler implements ResponseHandler { - private final CompletableFuture future; - - public DiscardResponseHandler(CompletableFuture future) { - this.future = Objects.requireNonNull(future, "future must not be null"); - } - - @Override - public void onSuccess(Map metadata) { - this.future.complete(new DiscardSummaryImpl(metadata)); - } - - @Override - public void onFailure(Throwable error) { - this.future.completeExceptionally(error); - } - - @Override - public void onRecord(Value[] fields) {} - - private record DiscardSummaryImpl(Map metadata) implements DiscardSummary { - @Override - public Map metadata() { - return metadata; - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/HelloResponseHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/HelloResponseHandler.java deleted file mode 100644 index 3d4459091e..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/HelloResponseHandler.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.handlers; - -import static java.util.Objects.requireNonNull; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.boltPatchesListeners; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.protocolVersion; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setConnectionId; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setConnectionReadTimeout; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setServerAgent; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.MetadataExtractor.extractBoltPatches; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.MetadataExtractor.extractServer; - -import io.netty.channel.Channel; -import java.time.Clock; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import java.util.function.Supplier; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v43.BoltProtocolV43; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v44.BoltProtocolV44; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.ResponseHandler; - -public class HelloResponseHandler implements ResponseHandler { - private static final String CONNECTION_ID_METADATA_KEY = "connection_id"; - public static final String CONFIGURATION_HINTS_KEY = "hints"; - public static final String CONNECTION_RECEIVE_TIMEOUT_SECONDS_KEY = "connection.recv_timeout_seconds"; - - private final CompletableFuture future; - private final Channel channel; - private final Clock clock; - private final CompletableFuture latestAuthMillisFuture; - - public HelloResponseHandler( - CompletableFuture future, - Channel channel, - Clock clock, - CompletableFuture latestAuthMillisFuture) { - requireNonNull(clock, "clock must not be null"); - this.future = future; - this.channel = channel; - this.clock = clock; - this.latestAuthMillisFuture = Objects.requireNonNull(latestAuthMillisFuture); - } - - @Override - public void onSuccess(Map metadata) { - try { - var serverAgent = extractServer(metadata).asString(); - setServerAgent(channel, serverAgent); - - var connectionId = extractConnectionId(metadata); - setConnectionId(channel, connectionId); - - processConfigurationHints(metadata); - - var protocolVersion = protocolVersion(channel); - if (BoltProtocolV44.VERSION.equals(protocolVersion) || BoltProtocolV43.VERSION.equals(protocolVersion)) { - var boltPatches = extractBoltPatches(metadata); - if (!boltPatches.isEmpty()) { - boltPatchesListeners(channel).forEach(listener -> listener.handle(boltPatches)); - } - } - - latestAuthMillisFuture.complete(clock.millis()); - future.complete(serverAgent); - } catch (Throwable error) { - onFailure(error); - throw error; - } - } - - @Override - public void onFailure(Throwable error) { - channel.close().addListener(future -> this.future.completeExceptionally(error)); - } - - @Override - public void onRecord(Value[] fields) { - throw new UnsupportedOperationException(); - } - - private static String extractConnectionId(Map metadata) { - var value = metadata.get(CONNECTION_ID_METADATA_KEY); - if (value == null || value.isNull()) { - throw new IllegalStateException("Unable to extract " + CONNECTION_ID_METADATA_KEY - + " from a response to HELLO message. " + "Received metadata: " + metadata); - } - return value.asString(); - } - - private void processConfigurationHints(Map metadata) { - var configurationHints = metadata.get(CONFIGURATION_HINTS_KEY); - if (configurationHints != null) { - getFromSupplierOrEmptyOnException(() -> configurationHints - .get(CONNECTION_RECEIVE_TIMEOUT_SECONDS_KEY) - .asLong()) - .ifPresent(timeout -> setConnectionReadTimeout(channel, timeout)); - } - } - - private static Optional getFromSupplierOrEmptyOnException(Supplier supplier) { - try { - return Optional.of(supplier.get()); - } catch (Exception e) { - return Optional.empty(); - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/HelloV51ResponseHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/HelloV51ResponseHandler.java deleted file mode 100644 index d2b6622435..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/HelloV51ResponseHandler.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.handlers; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setConnectionId; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setConnectionReadTimeout; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setServerAgent; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setSsrEnabled; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setTelemetryEnabled; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.MetadataExtractor.extractServer; - -import io.netty.channel.Channel; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import java.util.function.Supplier; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.ResponseHandler; - -public class HelloV51ResponseHandler implements ResponseHandler { - private static final String CONNECTION_ID_METADATA_KEY = "connection_id"; - public static final String CONFIGURATION_HINTS_KEY = "hints"; - public static final String CONNECTION_RECEIVE_TIMEOUT_SECONDS_KEY = "connection.recv_timeout_seconds"; - public static final String TELEMETRY_ENABLED_KEY = "telemetry.enabled"; - public static final String SSR_ENABLED_KEY = "ssr.enabled"; - - private final Channel channel; - private final CompletableFuture helloFuture; - - public HelloV51ResponseHandler(Channel channel, CompletableFuture helloFuture) { - this.channel = channel; - this.helloFuture = helloFuture; - } - - @Override - public void onSuccess(Map metadata) { - try { - var serverAgent = extractServer(metadata).asString(); - setServerAgent(channel, serverAgent); - - var connectionId = extractConnectionId(metadata); - setConnectionId(channel, connectionId); - - processConfigurationHints(metadata); - - helloFuture.complete(serverAgent); - } catch (Throwable error) { - onFailure(error); - throw error; - } - } - - @Override - public void onFailure(Throwable error) { - channel.close().addListener(future -> helloFuture.completeExceptionally(error)); - } - - @Override - public void onRecord(Value[] fields) { - throw new UnsupportedOperationException(); - } - - private void processConfigurationHints(Map metadata) { - var configurationHints = metadata.get(CONFIGURATION_HINTS_KEY); - if (configurationHints != null) { - getFromSupplierOrEmptyOnException(() -> configurationHints - .get(CONNECTION_RECEIVE_TIMEOUT_SECONDS_KEY) - .asLong()) - .ifPresent(timeout -> setConnectionReadTimeout(channel, timeout)); - - getFromSupplierOrEmptyOnException(() -> { - var value = configurationHints.get(TELEMETRY_ENABLED_KEY); - return !value.isNull() && value.asBoolean(); - }) - .ifPresent(telemetryEnabled -> setTelemetryEnabled(channel, telemetryEnabled)); - - getFromSupplierOrEmptyOnException(() -> { - var value = configurationHints.get(SSR_ENABLED_KEY); - return !value.isNull() && value.asBoolean(); - }) - .ifPresent(telemetryEnabled -> setSsrEnabled(channel, telemetryEnabled)); - } - } - - private static String extractConnectionId(Map metadata) { - var value = metadata.get(CONNECTION_ID_METADATA_KEY); - if (value == null || value.isNull()) { - throw new IllegalStateException("Unable to extract " + CONNECTION_ID_METADATA_KEY - + " from a response to HELLO message. " + "Received metadata: " + metadata); - } - return value.asString(); - } - - private static Optional getFromSupplierOrEmptyOnException(Supplier supplier) { - try { - return Optional.of(supplier.get()); - } catch (Exception e) { - return Optional.empty(); - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/LogoffResponseHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/LogoffResponseHandler.java deleted file mode 100644 index 6d71303523..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/LogoffResponseHandler.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.handlers; - -import static java.util.Objects.requireNonNull; - -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import org.neo4j.driver.internal.bolt.api.exception.BoltProtocolException; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.ResponseHandler; - -public class LogoffResponseHandler implements ResponseHandler { - private final CompletableFuture future; - - public LogoffResponseHandler(CompletableFuture future) { - this.future = requireNonNull(future, "future must not be null"); - } - - @Override - public void onSuccess(Map metadata) { - future.complete(null); - } - - @Override - public void onFailure(Throwable error) { - future.completeExceptionally(error); - } - - @Override - public void onRecord(Value[] fields) { - this.future.completeExceptionally(new BoltProtocolException("Records are not supported on LOGON")); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/LogonResponseHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/LogonResponseHandler.java deleted file mode 100644 index aefaa9b6d0..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/LogonResponseHandler.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.handlers; - -import static java.util.Objects.requireNonNull; - -import io.netty.channel.Channel; -import java.time.Clock; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import org.neo4j.driver.internal.bolt.api.exception.BoltProtocolException; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.ResponseHandler; - -public class LogonResponseHandler implements ResponseHandler { - private final CompletableFuture future; - private final Channel channel; - private final Clock clock; - private final CompletableFuture latestAuthMillisFuture; - - public LogonResponseHandler( - CompletableFuture future, Channel channel, Clock clock, CompletableFuture latestAuthMillisFuture) { - this.future = requireNonNull(future, "future must not be null"); - this.channel = channel; - this.clock = requireNonNull(clock, "clock must not be null"); - this.latestAuthMillisFuture = requireNonNull(latestAuthMillisFuture); - } - - @Override - public void onSuccess(Map metadata) { - latestAuthMillisFuture.complete(clock.millis()); - future.complete(null); - } - - @Override - public void onFailure(Throwable error) { - if (channel != null) { - channel.close().addListener(future -> this.future.completeExceptionally(error)); - } else { - future.completeExceptionally(error); - } - } - - @Override - public void onRecord(Value[] fields) { - future.completeExceptionally(new BoltProtocolException("Records are not supported on LOGON")); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/NoOpResponseHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/NoOpResponseHandler.java deleted file mode 100644 index 47596800b0..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/NoOpResponseHandler.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.handlers; - -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.ResponseHandler; - -public class NoOpResponseHandler implements ResponseHandler { - public static final NoOpResponseHandler INSTANCE = new NoOpResponseHandler(); - - @Override - public void onSuccess(Map metadata) {} - - @Override - public void onFailure(Throwable error) {} - - @Override - public void onRecord(Value[] fields) {} -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/PullResponseCompletionListener.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/PullResponseCompletionListener.java deleted file mode 100644 index fb302bd84a..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/PullResponseCompletionListener.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.handlers; - -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public interface PullResponseCompletionListener { - void afterSuccess(Map metadata); - - void afterFailure(Throwable error); -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/PullResponseHandlerImpl.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/PullResponseHandlerImpl.java deleted file mode 100644 index ded72125b7..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/PullResponseHandlerImpl.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.handlers; - -import java.util.Map; -import java.util.Objects; -import org.neo4j.driver.internal.bolt.api.summary.PullSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.PullMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.ResponseHandler; - -public class PullResponseHandlerImpl implements ResponseHandler { - private final PullMessageHandler handler; - private final ValueFactory valueFactory; - - public PullResponseHandlerImpl(PullMessageHandler handler, ValueFactory valueFactory) { - this.handler = handler; - this.valueFactory = Objects.requireNonNull(valueFactory); - } - - @Override - public void onSuccess(Map metadata) { - var hasMore = - metadata.getOrDefault("has_more", valueFactory.value(false)).asBoolean(); - handler.onSummary(new PullSummaryImpl(hasMore, metadata)); - } - - @Override - public void onFailure(Throwable throwable) { - handler.onError(throwable); - } - - @Override - public void onRecord(Value[] fields) { - handler.onRecord(fields); - } - - public record PullSummaryImpl(boolean hasMore, Map metadata) implements PullSummary {} -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/ResetResponseHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/ResetResponseHandler.java deleted file mode 100644 index f31d0a426f..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/ResetResponseHandler.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.handlers; - -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.ResponseHandler; - -public class ResetResponseHandler implements ResponseHandler { - private final CompletableFuture completionFuture; - private final Throwable throwable; - - public ResetResponseHandler(CompletableFuture completionFuture) { - this(completionFuture, null); - } - - public ResetResponseHandler(CompletableFuture completionFuture, Throwable throwable) { - this.completionFuture = completionFuture; - this.throwable = throwable; - } - - @Override - public final void onSuccess(Map metadata) { - resetCompleted(); - } - - @Override - public final void onFailure(Throwable error) { - if (completionFuture != null) { - completionFuture.completeExceptionally(error); - } - } - - @Override - public final void onRecord(Value[] fields) { - throw new UnsupportedOperationException(); - } - - public Optional throwable() { - return Optional.ofNullable(throwable); - } - - private void resetCompleted() { - if (completionFuture != null) { - completionFuture.complete(null); - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/RollbackTxResponseHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/RollbackTxResponseHandler.java deleted file mode 100644 index 36cd9c7cb9..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/RollbackTxResponseHandler.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.handlers; - -import static java.util.Objects.requireNonNull; - -import java.util.Arrays; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.ResponseHandler; - -public class RollbackTxResponseHandler implements ResponseHandler { - private final CompletableFuture rollbackFuture; - - public RollbackTxResponseHandler(CompletableFuture rollbackFuture) { - this.rollbackFuture = requireNonNull(rollbackFuture); - } - - @Override - public void onSuccess(Map metadata) { - rollbackFuture.complete(null); - } - - @Override - public void onFailure(Throwable error) { - rollbackFuture.completeExceptionally(error); - } - - @Override - public void onRecord(Value[] fields) { - throw new UnsupportedOperationException( - "Transaction rollback is not expected to receive records: " + Arrays.toString(fields)); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/RouteMessageResponseHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/RouteMessageResponseHandler.java deleted file mode 100644 index b5dc67cb31..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/RouteMessageResponseHandler.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.handlers; - -import static java.util.Objects.requireNonNull; - -import java.util.Arrays; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.CompletableFuture; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.ResponseHandler; - -/** - * Handles the RouteMessage response getting the success response - * and return its routing table property as the response. - */ -public class RouteMessageResponseHandler implements ResponseHandler { - private final CompletableFuture> completableFuture; - private final ValueFactory valueFactory; - - public RouteMessageResponseHandler( - final CompletableFuture> completableFuture, ValueFactory valueFactory) { - this.completableFuture = requireNonNull(completableFuture); - this.valueFactory = requireNonNull(valueFactory); - } - - @Override - public void onSuccess(Map metadata) { - try { - completableFuture.complete(metadata.get("rt").asMap(valueFactory::value)); - } catch (Exception ex) { - completableFuture.completeExceptionally(ex); - } - } - - @Override - public void onFailure(Throwable error) { - completableFuture.completeExceptionally(error); - } - - @Override - public void onRecord(Value[] fields) { - completableFuture.completeExceptionally(new UnsupportedOperationException( - "Route is not expected to receive records: " + Arrays.toString(fields))); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - var that = (RouteMessageResponseHandler) o; - return completableFuture.equals(that.completableFuture); - } - - @Override - public int hashCode() { - return Objects.hash(completableFuture); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/RunResponseHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/RunResponseHandler.java deleted file mode 100644 index 904b2fd4db..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/RunResponseHandler.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.handlers; - -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.ResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.MetadataExtractor; - -public class RunResponseHandler implements ResponseHandler { - private final CompletableFuture runFuture; - private final MetadataExtractor metadataExtractor; - - public RunResponseHandler(CompletableFuture runFuture, MetadataExtractor metadataExtractor) { - this.runFuture = runFuture; - this.metadataExtractor = metadataExtractor; - } - - @Override - public void onSuccess(Map metadata) { - var queryKeys = metadataExtractor.extractQueryKeys(metadata); - var resultAvailableAfter = metadataExtractor.extractResultAvailableAfter(metadata); - var queryId = metadataExtractor.extractQueryId(metadata); - var db = metadata.get("db"); - var databaseName = db != null ? db.asString() : null; - - runFuture.complete(new RunResponseImpl(queryId, queryKeys, resultAvailableAfter, databaseName)); - } - - @Override - public void onFailure(Throwable error) { - runFuture.completeExceptionally(error); - } - - @Override - public void onRecord(Value[] fields) { - throw new UnsupportedOperationException(); - } - - private record RunResponseImpl(long queryId, List keys, long resultAvailableAfter, String database) - implements RunSummary { - @Override - public Optional databaseName() { - return Optional.ofNullable(database); - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/TelemetryResponseHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/TelemetryResponseHandler.java deleted file mode 100644 index b02cd9d14a..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/TelemetryResponseHandler.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.handlers; - -import static java.util.Objects.requireNonNull; - -import java.util.Arrays; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.TelemetryMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.ResponseHandler; - -/** - * Handles {@link TelemetryMessage} responses. - * - */ -public class TelemetryResponseHandler implements ResponseHandler { - private final CompletableFuture future; - - /** - * Constructor - * - * @param future The future which will be resolved - */ - public TelemetryResponseHandler(CompletableFuture future) { - this.future = requireNonNull(future); - } - - @Override - public void onSuccess(Map metadata) { - future.complete(null); - } - - @Override - public void onFailure(Throwable error) { - future.completeExceptionally(error); - } - - @Override - public void onRecord(Value[] fields) { - throw new UnsupportedOperationException( - "Telemetry is not expected to receive records: " + Arrays.toString(fields)); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/logging/ChannelActivityLogger.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/logging/ChannelActivityLogger.java deleted file mode 100644 index 22e65cfab2..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/logging/ChannelActivityLogger.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.logging; - -import static java.lang.String.format; - -import io.netty.channel.Channel; -import java.util.ResourceBundle; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; - -public class ChannelActivityLogger implements System.Logger { - private final Channel channel; - private final String localChannelId; - private final System.Logger delegate; - - private String dbConnectionId; - private String serverAddress; - - public ChannelActivityLogger(Channel channel, LoggingProvider logging, Class owner) { - this(channel, logging.getLog(owner)); - } - - private ChannelActivityLogger(Channel channel, System.Logger delegate) { - this.channel = channel; - this.delegate = delegate; - this.localChannelId = channel != null ? channel.id().toString() : null; - } - - @Override - public String getName() { - return delegate.getName(); - } - - @Override - public boolean isLoggable(Level level) { - return delegate.isLoggable(level); - } - - @Override - public void log(Level level, ResourceBundle bundle, String msg, Throwable thrown) { - delegate.log(level, bundle, reformat(msg), thrown); - } - - @Override - public void log(Level level, ResourceBundle bundle, String format, Object... params) { - delegate.log(level, bundle, reformat(format), params); - } - - String reformat(String message) { - if (channel == null) { - return message; - } - - var dbConnectionId = getDbConnectionId(); - var serverAddress = getServerAddress(); - - return format( - "[0x%s][%s][%s] %s", - localChannelId, valueOrEmpty(serverAddress), valueOrEmpty(dbConnectionId), message); - } - - private String getDbConnectionId() { - if (dbConnectionId == null) { - dbConnectionId = ChannelAttributes.connectionId(channel); - } - return dbConnectionId; - } - - private String getServerAddress() { - - if (serverAddress == null) { - var serverAddress = ChannelAttributes.serverAddress(channel); - this.serverAddress = serverAddress != null ? serverAddress.toString() : null; - } - - return serverAddress; - } - - /** - * Returns the submitted value if it is not null or an empty string if it is. - */ - private static String valueOrEmpty(String value) { - return value != null ? value : ""; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/logging/ChannelErrorLogger.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/logging/ChannelErrorLogger.java deleted file mode 100644 index 21e3b768f2..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/logging/ChannelErrorLogger.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.logging; - -import io.netty.channel.Channel; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; - -/** - * Dedicated logger for channel error logging. - *

- * It keeps messages shorter in debug mode and provides more details in trace mode. - */ -public class ChannelErrorLogger extends ChannelActivityLogger { - private static final String DEBUG_MESSAGE_FORMAT = "%s (%s)"; - - public ChannelErrorLogger(Channel channel, LoggingProvider logging) { - super(channel, logging, ChannelErrorLogger.class); - } - - public void traceOrDebug(String message, Throwable error) { - if (isLoggable(Level.TRACE)) { - log(Level.ERROR, message, error); - } else { - log(Level.DEBUG, String.format(DEBUG_MESSAGE_FORMAT, message, error.getClass())); - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/AbstractMessageWriter.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/AbstractMessageWriter.java deleted file mode 100644 index 5793673012..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/AbstractMessageWriter.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging; - -import static java.util.Objects.requireNonNull; - -import java.io.IOException; -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; - -public abstract class AbstractMessageWriter implements MessageFormat.Writer { - private final ValuePacker packer; - private final Map encodersByMessageSignature; - private final ValueFactory valueFactory; - - protected AbstractMessageWriter( - ValuePacker packer, Map encodersByMessageSignature, ValueFactory valueFactory) { - this.packer = requireNonNull(packer); - this.encodersByMessageSignature = requireNonNull(encodersByMessageSignature); - this.valueFactory = requireNonNull(valueFactory); - } - - @Override - public final void write(Message msg) throws IOException { - var signature = msg.signature(); - var encoder = encodersByMessageSignature.get(signature); - if (encoder == null) { - throw new IOException("No encoder found for message " + msg + " with signature " + signature); - } - encoder.encode(msg, packer, valueFactory); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/BoltPatchesListener.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/BoltPatchesListener.java deleted file mode 100644 index 6584400b3d..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/BoltPatchesListener.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging; - -import java.util.Set; - -public interface BoltPatchesListener { - String DATE_TIME_UTC_PATCH = "utc"; - - void handle(Set patches); -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/BoltProtocol.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/BoltProtocol.java deleted file mode 100644 index 19bb66cd0a..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/BoltProtocol.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.protocolVersion; - -import io.netty.channel.Channel; -import java.time.Clock; -import java.time.Duration; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.BoltAgent; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.exception.BoltClientException; -import org.neo4j.driver.internal.bolt.api.exception.BoltUnsupportedFeatureException; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.DiscardSummary; -import org.neo4j.driver.internal.bolt.api.summary.RouteSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.BoltProtocolUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public interface BoltProtocol { - MessageFormat createMessageFormat(); - - CompletionStage initializeChannel( - Channel channel, - String userAgent, - BoltAgent boltAgent, - Map authMap, - RoutingContext routingContext, - NotificationConfig notificationConfig, - Clock clock, - CompletableFuture latestAuthMillisFuture, - ValueFactory valueFactory); - - CompletionStage route( - Connection connection, - Map routingContext, - Set bookmarks, - String databaseName, - String impersonatedUser, - MessageHandler handler, - Clock clock, - LoggingProvider logging, - ValueFactory valueFactory); - - CompletionStage beginTransaction( - Connection connection, - DatabaseName databaseName, - AccessMode accessMode, - String impersonatedUser, - Set bookmarks, - Duration txTimeout, - Map txMetadata, - String txType, - NotificationConfig notificationConfig, - MessageHandler handler, - LoggingProvider logging, - ValueFactory valueFactory); - - CompletionStage commitTransaction(Connection connection, MessageHandler handler); - - CompletionStage rollbackTransaction(Connection connection, MessageHandler handler); - - CompletionStage telemetry(Connection connection, Integer api, MessageHandler handler); - - CompletionStage runAuto( - Connection connection, - DatabaseName databaseName, - AccessMode accessMode, - String impersonatedUser, - String query, - Map parameters, - Set bookmarks, - Duration txTimeout, - Map txMetadata, - NotificationConfig notificationConfig, - MessageHandler handler, - LoggingProvider logging, - ValueFactory valueFactory); - - CompletionStage run( - Connection connection, String query, Map parameters, MessageHandler handler); - - CompletionStage pull( - Connection connection, long qid, long request, PullMessageHandler handler, ValueFactory valueFactory); - - CompletionStage discard( - Connection connection, - long qid, - long number, - MessageHandler handler, - ValueFactory valueFactory); - - CompletionStage reset(Connection connection, MessageHandler handler); - - default CompletionStage logoff(Connection connection, MessageHandler handler) { - return CompletableFuture.failedStage(new BoltUnsupportedFeatureException("logoff not supported")); - } - - default CompletionStage logon( - Connection connection, - Map authMap, - Clock clock, - MessageHandler handler, - ValueFactory valueFactory) { - return CompletableFuture.failedStage(new BoltUnsupportedFeatureException("logon not supported")); - } - - /** - * Returns the protocol version. It can be used for version specific error messages. - * @return the protocol version. - */ - BoltProtocolVersion version(); - - static BoltProtocol forChannel(Channel channel) { - return forVersion(protocolVersion(channel)); - } - - static BoltProtocol forVersion(BoltProtocolVersion version) { - var protocol = BoltProtocolUtil.versionToProtocol.get(version); - if (protocol != null) { - return protocol; - } else { - throw new BoltClientException("Unknown protocol version: " + version); - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/Message.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/Message.java deleted file mode 100644 index dd77b8e4d6..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/Message.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging; - -/** - * Base class for all protocol messages. - */ -public interface Message { - byte signature(); -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/MessageEncoder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/MessageEncoder.java deleted file mode 100644 index dc1a9a4041..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/MessageEncoder.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging; - -import java.io.IOException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; - -public interface MessageEncoder { - void encode(Message message, ValuePacker packer, ValueFactory valueFactory) throws IOException; -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/MessageFormat.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/MessageFormat.java deleted file mode 100644 index 218771c1d6..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/MessageFormat.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging; - -import java.io.IOException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -public interface MessageFormat { - interface Writer { - void write(Message msg) throws IOException; - } - - interface Reader { - void read(ResponseMessageHandler handler) throws IOException; - } - - Writer newWriter(PackOutput output, ValueFactory valueFactory); - - Reader newReader(PackInput input, ValueFactory valueFactory); - - /** - * Enables datetime in UTC if supported by the given message format. This is only for use with formats that support multiple modes. - *

- * This only takes effect on subsequent writer and reader creation via {@link #newWriter(PackOutput, ValueFactory)} and {@link #newReader(PackInput, ValueFactory)}. - */ - default void enableDateTimeUtc() {} -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/MessageHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/MessageHandler.java deleted file mode 100644 index 7b67fe07ee..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/MessageHandler.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging; - -public interface MessageHandler { - void onError(Throwable throwable); - - void onSummary(T summary); -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/PullMessageHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/PullMessageHandler.java deleted file mode 100644 index 9ca5346f98..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/PullMessageHandler.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging; - -import org.neo4j.driver.internal.bolt.api.summary.PullSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public interface PullMessageHandler extends MessageHandler { - void onRecord(Value[] fields); -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/ResponseMessageHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/ResponseMessageHandler.java deleted file mode 100644 index 2cd81da268..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/ResponseMessageHandler.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging; - -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.GqlError; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public interface ResponseMessageHandler { - void handleSuccessMessage(Map meta); - - void handleRecordMessage(Value[] fields); - - void handleFailureMessage(GqlError gqlError); - - void handleIgnoredMessage(); -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/ValuePacker.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/ValuePacker.java deleted file mode 100644 index b85c6168fa..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/ValuePacker.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging; - -import java.io.IOException; -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public interface ValuePacker { - void packStructHeader(int size, byte signature) throws IOException; - - void pack(String string) throws IOException; - - void pack(Value value) throws IOException; - - void pack(Map map) throws IOException; -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/ValueUnpacker.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/ValueUnpacker.java deleted file mode 100644 index 9e646cfaed..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/ValueUnpacker.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging; - -import java.io.IOException; -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public interface ValueUnpacker { - @SuppressWarnings("UnusedReturnValue") - long unpackStructHeader() throws IOException; - - int unpackStructSignature() throws IOException; - - Map unpackMap() throws IOException; - - Value[] unpackArray() throws IOException; -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/common/CommonMessageReader.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/common/CommonMessageReader.java deleted file mode 100644 index 50844d9c3e..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/common/CommonMessageReader.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common; - -import java.io.IOException; -import java.util.Map; -import java.util.Objects; -import org.neo4j.driver.internal.bolt.api.GqlError; -import org.neo4j.driver.internal.bolt.api.GqlStatusError; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ResponseMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValueUnpacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.FailureMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.IgnoredMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.RecordMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.SuccessMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; - -public class CommonMessageReader implements MessageFormat.Reader { - protected final ValueUnpacker unpacker; - protected final ValueFactory valueFactory; - - public CommonMessageReader(PackInput input, boolean dateTimeUtcEnabled, ValueFactory valueFactory) { - this(new CommonValueUnpacker(input, dateTimeUtcEnabled, valueFactory), valueFactory); - } - - protected CommonMessageReader(ValueUnpacker unpacker, ValueFactory valueFactory) { - this.unpacker = unpacker; - this.valueFactory = Objects.requireNonNull(valueFactory); - } - - @Override - public void read(ResponseMessageHandler handler) throws IOException { - unpacker.unpackStructHeader(); - var type = unpacker.unpackStructSignature(); - switch (type) { - case SuccessMessage.SIGNATURE -> unpackSuccessMessage(handler); - case FailureMessage.SIGNATURE -> unpackFailureMessage(handler); - case IgnoredMessage.SIGNATURE -> unpackIgnoredMessage(handler); - case RecordMessage.SIGNATURE -> unpackRecordMessage(handler); - default -> throw new IOException("Unknown message type: " + type); - } - } - - private void unpackSuccessMessage(ResponseMessageHandler output) throws IOException { - var map = unpacker.unpackMap(); - output.handleSuccessMessage(map); - } - - protected void unpackFailureMessage(ResponseMessageHandler output) throws IOException { - var params = unpacker.unpackMap(); - var code = params.get("code").asString(); - var message = params.get("message").asString(); - var diagnosticRecord = Map.ofEntries( - Map.entry("CURRENT_SCHEMA", valueFactory.value("/")), - Map.entry("OPERATION", valueFactory.value("")), - Map.entry("OPERATION_CODE", valueFactory.value("0"))); - var gqlError = new GqlError( - GqlStatusError.UNKNOWN.getStatus(), - GqlStatusError.UNKNOWN.getStatusDescription(message), - code, - message, - diagnosticRecord, - null); - output.handleFailureMessage(gqlError); - } - - private void unpackIgnoredMessage(ResponseMessageHandler output) { - output.handleIgnoredMessage(); - } - - private void unpackRecordMessage(ResponseMessageHandler output) throws IOException { - var fields = unpacker.unpackArray(); - output.handleRecordMessage(fields); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/common/CommonValuePacker.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/common/CommonValuePacker.java deleted file mode 100644 index bc4475d4e7..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/common/CommonValuePacker.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common; - -import static java.time.ZoneOffset.UTC; - -import java.io.IOException; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.IsoDuration; -import org.neo4j.driver.internal.bolt.api.values.Point; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackStream; - -public class CommonValuePacker implements ValuePacker { - - public static final byte DATE = 'D'; - public static final int DATE_STRUCT_SIZE = 1; - - public static final byte TIME = 'T'; - public static final int TIME_STRUCT_SIZE = 2; - - public static final byte LOCAL_TIME = 't'; - public static final int LOCAL_TIME_STRUCT_SIZE = 1; - - public static final byte LOCAL_DATE_TIME = 'd'; - public static final int LOCAL_DATE_TIME_STRUCT_SIZE = 2; - - public static final byte DATE_TIME_WITH_ZONE_OFFSET = 'F'; - public static final byte DATE_TIME_WITH_ZONE_OFFSET_UTC = 'I'; - public static final byte DATE_TIME_WITH_ZONE_ID = 'f'; - public static final byte DATE_TIME_WITH_ZONE_ID_UTC = 'i'; - public static final int DATE_TIME_STRUCT_SIZE = 3; - - public static final byte DURATION = 'E'; - public static final int DURATION_TIME_STRUCT_SIZE = 4; - - public static final byte POINT_2D_STRUCT_TYPE = 'X'; - public static final int POINT_2D_STRUCT_SIZE = 3; - - public static final byte POINT_3D_STRUCT_TYPE = 'Y'; - public static final int POINT_3D_STRUCT_SIZE = 4; - - private final boolean dateTimeUtcEnabled; - protected final PackStream.Packer packer; - - public CommonValuePacker(PackOutput output, boolean dateTimeUtcEnabled) { - this.dateTimeUtcEnabled = dateTimeUtcEnabled; - this.packer = new PackStream.Packer(output); - } - - @Override - public final void packStructHeader(int size, byte signature) throws IOException { - packer.packStructHeader(size, signature); - } - - @Override - public final void pack(String string) throws IOException { - packer.pack(string); - } - - @Override - public final void pack(Value value) throws IOException { - packInternalValue(value); - } - - @Override - public final void pack(Map map) throws IOException { - if (map == null || map.isEmpty()) { - packer.packMapHeader(0); - return; - } - packer.packMapHeader(map.size()); - for (var entry : map.entrySet()) { - packer.pack(entry.getKey()); - pack(entry.getValue()); - } - } - - protected void packInternalValue(Value value) throws IOException { - switch (value.type()) { - case DATE -> packDate(value.asLocalDate()); - case TIME -> packTime(value.asOffsetTime()); - case LOCAL_TIME -> packLocalTime(value.asLocalTime()); - case LOCAL_DATE_TIME -> packLocalDateTime(value.asLocalDateTime()); - case DATE_TIME -> { - if (dateTimeUtcEnabled) { - packZonedDateTimeUsingUtcBaseline(value.asZonedDateTime()); - } else { - packZonedDateTime(value.asZonedDateTime()); - } - } - case DURATION -> packDuration(value.asIsoDuration()); - case POINT -> packPoint(value.asPoint()); - case NULL -> packer.packNull(); - case BYTES -> packer.pack(value.asByteArray()); - case STRING -> packer.pack(value.asString()); - case BOOLEAN -> packer.pack(value.asBoolean()); - case INTEGER -> packer.pack(value.asLong()); - case FLOAT -> packer.pack(value.asDouble()); - case MAP -> { - packer.packMapHeader(value.size()); - for (var s : value.keys()) { - packer.pack(s); - pack(value.get(s)); - } - } - case LIST -> { - packer.packListHeader(value.size()); - for (var item : value.values()) { - pack(item); - } - } - default -> throw new IOException("Unknown type: " + value.type().name()); - } - } - - private void packDate(LocalDate localDate) throws IOException { - packer.packStructHeader(DATE_STRUCT_SIZE, DATE); - packer.pack(localDate.toEpochDay()); - } - - private void packTime(OffsetTime offsetTime) throws IOException { - var nanoOfDayLocal = offsetTime.toLocalTime().toNanoOfDay(); - var offsetSeconds = offsetTime.getOffset().getTotalSeconds(); - - packer.packStructHeader(TIME_STRUCT_SIZE, TIME); - packer.pack(nanoOfDayLocal); - packer.pack(offsetSeconds); - } - - private void packLocalTime(LocalTime localTime) throws IOException { - packer.packStructHeader(LOCAL_TIME_STRUCT_SIZE, LOCAL_TIME); - packer.pack(localTime.toNanoOfDay()); - } - - private void packLocalDateTime(LocalDateTime localDateTime) throws IOException { - var epochSecondUtc = localDateTime.toEpochSecond(UTC); - var nano = localDateTime.getNano(); - - packer.packStructHeader(LOCAL_DATE_TIME_STRUCT_SIZE, LOCAL_DATE_TIME); - packer.pack(epochSecondUtc); - packer.pack(nano); - } - - @SuppressWarnings("DuplicatedCode") - private void packZonedDateTimeUsingUtcBaseline(ZonedDateTime zonedDateTime) throws IOException { - var instant = zonedDateTime.toInstant(); - var epochSecondLocal = instant.getEpochSecond(); - var nano = zonedDateTime.getNano(); - var zone = zonedDateTime.getZone(); - - if (zone instanceof ZoneOffset) { - var offsetSeconds = ((ZoneOffset) zone).getTotalSeconds(); - - packer.packStructHeader(DATE_TIME_STRUCT_SIZE, DATE_TIME_WITH_ZONE_OFFSET_UTC); - packer.pack(epochSecondLocal); - packer.pack(nano); - packer.pack(offsetSeconds); - } else { - var zoneId = zone.getId(); - - packer.packStructHeader(DATE_TIME_STRUCT_SIZE, DATE_TIME_WITH_ZONE_ID_UTC); - packer.pack(epochSecondLocal); - packer.pack(nano); - packer.pack(zoneId); - } - } - - @SuppressWarnings("DuplicatedCode") - private void packZonedDateTime(ZonedDateTime zonedDateTime) throws IOException { - var epochSecondLocal = zonedDateTime.toLocalDateTime().toEpochSecond(UTC); - var nano = zonedDateTime.getNano(); - - var zone = zonedDateTime.getZone(); - if (zone instanceof ZoneOffset) { - var offsetSeconds = ((ZoneOffset) zone).getTotalSeconds(); - - packer.packStructHeader(DATE_TIME_STRUCT_SIZE, DATE_TIME_WITH_ZONE_OFFSET); - packer.pack(epochSecondLocal); - packer.pack(nano); - packer.pack(offsetSeconds); - } else { - var zoneId = zone.getId(); - - packer.packStructHeader(DATE_TIME_STRUCT_SIZE, DATE_TIME_WITH_ZONE_ID); - packer.pack(epochSecondLocal); - packer.pack(nano); - packer.pack(zoneId); - } - } - - private void packDuration(IsoDuration duration) throws IOException { - packer.packStructHeader(DURATION_TIME_STRUCT_SIZE, DURATION); - packer.pack(duration.months()); - packer.pack(duration.days()); - packer.pack(duration.seconds()); - packer.pack(duration.nanoseconds()); - } - - private void packPoint(Point point) throws IOException { - if (Double.isNaN(point.z())) { - packPoint2D(point); - } else { - packPoint3D(point); - } - } - - private void packPoint2D(Point point) throws IOException { - packer.packStructHeader(POINT_2D_STRUCT_SIZE, POINT_2D_STRUCT_TYPE); - packer.pack(point.srid()); - packer.pack(point.x()); - packer.pack(point.y()); - } - - private void packPoint3D(Point point) throws IOException { - packer.packStructHeader(POINT_3D_STRUCT_SIZE, POINT_3D_STRUCT_TYPE); - packer.pack(point.srid()); - packer.pack(point.x()); - packer.pack(point.y()); - packer.pack(point.z()); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/common/CommonValueUnpacker.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/common/CommonValueUnpacker.java deleted file mode 100644 index 1f69c62f98..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/common/CommonValueUnpacker.java +++ /dev/null @@ -1,466 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common; - -import static java.time.ZoneOffset.UTC; - -import java.io.IOException; -import java.time.DateTimeException; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.Supplier; -import org.neo4j.driver.internal.bolt.api.exception.BoltClientException; -import org.neo4j.driver.internal.bolt.api.exception.BoltProtocolException; -import org.neo4j.driver.internal.bolt.api.values.Node; -import org.neo4j.driver.internal.bolt.api.values.Path; -import org.neo4j.driver.internal.bolt.api.values.Relationship; -import org.neo4j.driver.internal.bolt.api.values.Segment; -import org.neo4j.driver.internal.bolt.api.values.Type; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValueUnpacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackStream; - -public class CommonValueUnpacker implements ValueUnpacker { - public static final byte DATE = 'D'; - public static final int DATE_STRUCT_SIZE = 1; - - public static final byte TIME = 'T'; - public static final int TIME_STRUCT_SIZE = 2; - - public static final byte LOCAL_TIME = 't'; - public static final int LOCAL_TIME_STRUCT_SIZE = 1; - - public static final byte LOCAL_DATE_TIME = 'd'; - public static final int LOCAL_DATE_TIME_STRUCT_SIZE = 2; - - public static final byte DATE_TIME_WITH_ZONE_OFFSET = 'F'; - public static final byte DATE_TIME_WITH_ZONE_OFFSET_UTC = 'I'; - public static final byte DATE_TIME_WITH_ZONE_ID = 'f'; - public static final byte DATE_TIME_WITH_ZONE_ID_UTC = 'i'; - public static final int DATE_TIME_STRUCT_SIZE = 3; - - public static final byte DURATION = 'E'; - public static final int DURATION_TIME_STRUCT_SIZE = 4; - - public static final byte POINT_2D_STRUCT_TYPE = 'X'; - public static final int POINT_2D_STRUCT_SIZE = 3; - - public static final byte POINT_3D_STRUCT_TYPE = 'Y'; - public static final int POINT_3D_STRUCT_SIZE = 4; - - public static final byte NODE = 'N'; - public static final byte RELATIONSHIP = 'R'; - public static final byte UNBOUND_RELATIONSHIP = 'r'; - public static final byte PATH = 'P'; - - private static final int NODE_FIELDS = 3; - private static final int RELATIONSHIP_FIELDS = 5; - - private final boolean dateTimeUtcEnabled; - protected final PackStream.Unpacker unpacker; - protected final ValueFactory valueFactory; - - public CommonValueUnpacker(PackInput input, boolean dateTimeUtcEnabled, ValueFactory valueFactory) { - this.dateTimeUtcEnabled = dateTimeUtcEnabled; - this.unpacker = new PackStream.Unpacker(input); - this.valueFactory = Objects.requireNonNull(valueFactory); - } - - @Override - public long unpackStructHeader() throws IOException { - return unpacker.unpackStructHeader(); - } - - @Override - public int unpackStructSignature() throws IOException { - return unpacker.unpackStructSignature(); - } - - @Override - public Map unpackMap() throws IOException { - var size = (int) unpacker.unpackMapHeader(); - if (size == 0) { - return Collections.emptyMap(); - } - Map map = new HashMap<>(size); - for (var i = 0; i < size; i++) { - var key = unpacker.unpackString(); - map.put(key, unpack()); - } - return map; - } - - @Override - public Value[] unpackArray() throws IOException { - var size = (int) unpacker.unpackListHeader(); - var values = new Value[size]; - for (var i = 0; i < size; i++) { - values[i] = unpack(); - } - return values; - } - - protected Value unpack() throws IOException { - var type = unpacker.peekNextType(); - switch (type) { - case NULL -> { - return valueFactory.value(unpacker.unpackNull()); - } - case BOOLEAN -> { - return valueFactory.value(unpacker.unpackBoolean()); - } - case INTEGER -> { - return valueFactory.value(unpacker.unpackLong()); - } - case FLOAT -> { - return valueFactory.value(unpacker.unpackDouble()); - } - case BYTES -> { - return valueFactory.value(unpacker.unpackBytes()); - } - case STRING -> { - return valueFactory.value(unpacker.unpackString()); - } - case MAP -> { - return valueFactory.value(unpackMap()); - } - case LIST -> { - var size = (int) unpacker.unpackListHeader(); - var vals = new Value[size]; - for (var j = 0; j < size; j++) { - vals[j] = unpack(); - } - return valueFactory.value(vals); - } - case STRUCT -> { - var size = unpacker.unpackStructHeader(); - var structType = unpacker.unpackStructSignature(); - return unpackStruct(size, structType); - } - } - throw new IOException("Unknown value type: " + type); - } - - private Value unpackStruct(long size, byte type) throws IOException { - switch (type) { - case DATE -> { - ensureCorrectStructSize(Type.DATE, DATE_STRUCT_SIZE, size); - return unpackDate(); - } - case TIME -> { - ensureCorrectStructSize(Type.TIME, TIME_STRUCT_SIZE, size); - return unpackTime(); - } - case LOCAL_TIME -> { - ensureCorrectStructSize(Type.LOCAL_TIME, LOCAL_TIME_STRUCT_SIZE, size); - return unpackLocalTime(); - } - case LOCAL_DATE_TIME -> { - ensureCorrectStructSize(Type.LOCAL_DATE_TIME, LOCAL_DATE_TIME_STRUCT_SIZE, size); - return unpackLocalDateTime(); - } - case DATE_TIME_WITH_ZONE_OFFSET -> { - if (!dateTimeUtcEnabled) { - ensureCorrectStructSize(Type.DATE_TIME, DATE_TIME_STRUCT_SIZE, size); - return unpackDateTime(ZoneMode.OFFSET, BaselineMode.LEGACY); - } else { - throw instantiateExceptionForUnknownType(type); - } - } - case DATE_TIME_WITH_ZONE_OFFSET_UTC -> { - if (dateTimeUtcEnabled) { - ensureCorrectStructSize(Type.DATE_TIME, DATE_TIME_STRUCT_SIZE, size); - return unpackDateTime(ZoneMode.OFFSET, BaselineMode.UTC); - } else { - throw instantiateExceptionForUnknownType(type); - } - } - case DATE_TIME_WITH_ZONE_ID -> { - if (!dateTimeUtcEnabled) { - ensureCorrectStructSize(Type.DATE_TIME, DATE_TIME_STRUCT_SIZE, size); - return unpackDateTime(ZoneMode.ZONE_ID, BaselineMode.LEGACY); - } else { - throw instantiateExceptionForUnknownType(type); - } - } - case DATE_TIME_WITH_ZONE_ID_UTC -> { - if (dateTimeUtcEnabled) { - ensureCorrectStructSize(Type.DATE_TIME, DATE_TIME_STRUCT_SIZE, size); - return unpackDateTime(ZoneMode.ZONE_ID, BaselineMode.UTC); - } else { - throw instantiateExceptionForUnknownType(type); - } - } - case DURATION -> { - ensureCorrectStructSize(Type.DURATION, DURATION_TIME_STRUCT_SIZE, size); - return unpackDuration(); - } - case POINT_2D_STRUCT_TYPE -> { - ensureCorrectStructSize(Type.POINT, POINT_2D_STRUCT_SIZE, size); - return unpackPoint2D(); - } - case POINT_3D_STRUCT_TYPE -> { - ensureCorrectStructSize(Type.POINT, POINT_3D_STRUCT_SIZE, size); - return unpackPoint3D(); - } - case NODE -> { - ensureCorrectStructSize(Type.NODE, getNodeFields(), size); - return valueFactory.value(unpackNode()); - } - case RELATIONSHIP -> { - ensureCorrectStructSize(Type.RELATIONSHIP, getRelationshipFields(), size); - return valueFactory.value(unpackRelationship()); - } - case PATH -> { - ensureCorrectStructSize(Type.PATH, 3, size); - return valueFactory.value(unpackPath()); - } - default -> throw instantiateExceptionForUnknownType(type); - } - } - - protected Relationship unpackRelationship() throws IOException { - var urn = unpacker.unpackLong(); - var startUrn = unpacker.unpackLong(); - var endUrn = unpacker.unpackLong(); - var relType = unpacker.unpackString(); - var props = unpackMap(); - - return valueFactory.relationship( - urn, - String.valueOf(urn), - startUrn, - String.valueOf(startUrn), - endUrn, - String.valueOf(endUrn), - relType, - props); - } - - @SuppressWarnings("DuplicatedCode") - protected Node unpackNode() throws IOException { - var urn = unpacker.unpackLong(); - - var numLabels = (int) unpacker.unpackListHeader(); - List labels = new ArrayList<>(numLabels); - for (var i = 0; i < numLabels; i++) { - labels.add(unpacker.unpackString()); - } - var numProps = (int) unpacker.unpackMapHeader(); - Map props = new HashMap<>(numProps); - for (var j = 0; j < numProps; j++) { - var key = unpacker.unpackString(); - props.put(key, unpack()); - } - - return valueFactory.node(urn, String.valueOf(urn), labels, props); - } - - @SuppressWarnings("DuplicatedCode") - protected Path unpackPath() throws IOException { - // List of unique nodes - var uniqNodes = new Node[(int) unpacker.unpackListHeader()]; - for (var i = 0; i < uniqNodes.length; i++) { - ensureCorrectStructSize(Type.NODE, getNodeFields(), unpacker.unpackStructHeader()); - ensureCorrectStructSignature("NODE", NODE, unpacker.unpackStructSignature()); - uniqNodes[i] = unpackNode(); - } - - // List of unique relationships, without start/end information - var uniqRels = new Relationship[(int) unpacker.unpackListHeader()]; - for (var i = 0; i < uniqRels.length; i++) { - ensureCorrectStructSize(Type.RELATIONSHIP, 3, unpacker.unpackStructHeader()); - ensureCorrectStructSignature( - "UNBOUND_RELATIONSHIP", UNBOUND_RELATIONSHIP, unpacker.unpackStructSignature()); - var id = unpacker.unpackLong(); - var relType = unpacker.unpackString(); - var props = unpackMap(); - uniqRels[i] = valueFactory.relationship( - id, String.valueOf(id), -1, String.valueOf(-1), -1, String.valueOf(-1), relType, props); - } - - // Path sequence - var length = (int) unpacker.unpackListHeader(); - - // Knowing the sequence length, we can create the arrays that will represent the nodes, rels and segments in - // their "path order" - var segments = new Segment[length / 2]; - var nodes = new Node[segments.length + 1]; - var rels = new Relationship[segments.length]; - - Node prevNode = uniqNodes[0], nextNode; // Start node is always 0, and isn't encoded in the sequence - nodes[0] = prevNode; - Relationship rel; - for (var i = 0; i < segments.length; i++) { - var relIdx = (int) unpacker.unpackLong(); - nextNode = uniqNodes[(int) unpacker.unpackLong()]; - // Negative rel index means this rel was traversed "inversed" from its direction - if (relIdx < 0) { - rel = uniqRels[(-relIdx) - 1]; // -1 because rel idx are 1-indexed - rel.setStartAndEnd( - nextNode.id(), String.valueOf(nextNode.id()), prevNode.id(), String.valueOf(prevNode.id())); - } else { - rel = uniqRels[relIdx - 1]; - rel.setStartAndEnd( - prevNode.id(), String.valueOf(prevNode.id()), nextNode.id(), String.valueOf(nextNode.id())); - } - - nodes[i + 1] = nextNode; - rels[i] = rel; - segments[i] = valueFactory.segment(prevNode, rel, nextNode); - prevNode = nextNode; - } - return valueFactory.path(Arrays.asList(segments), Arrays.asList(nodes), Arrays.asList(rels)); - } - - protected final void ensureCorrectStructSize(Type type, int expected, long actual) { - if (expected != actual) { - var structName = type.toString(); - throw new BoltClientException(String.format( - "Invalid message received, serialized %s structures should have %d fields, " - + "received %s structure has %d fields.", - structName, expected, structName, actual)); - } - } - - protected void ensureCorrectStructSignature(String structName, byte expected, byte actual) { - if (expected != actual) { - throw new BoltClientException(String.format( - "Invalid message received, expected a `%s`, signature 0x%s. Received signature was 0x%s.", - structName, Integer.toHexString(expected), Integer.toHexString(actual))); - } - } - - private Value unpackDate() throws IOException { - var epochDay = unpacker.unpackLong(); - return valueFactory.value(LocalDate.ofEpochDay(epochDay)); - } - - private Value unpackTime() throws IOException { - var nanoOfDayLocal = unpacker.unpackLong(); - var offsetSeconds = Math.toIntExact(unpacker.unpackLong()); - - var localTime = LocalTime.ofNanoOfDay(nanoOfDayLocal); - var offset = ZoneOffset.ofTotalSeconds(offsetSeconds); - return valueFactory.value(OffsetTime.of(localTime, offset)); - } - - private Value unpackLocalTime() throws IOException { - var nanoOfDayLocal = unpacker.unpackLong(); - return valueFactory.value(LocalTime.ofNanoOfDay(nanoOfDayLocal)); - } - - private Value unpackLocalDateTime() throws IOException { - var epochSecondUtc = unpacker.unpackLong(); - var nano = Math.toIntExact(unpacker.unpackLong()); - return valueFactory.value(LocalDateTime.ofEpochSecond(epochSecondUtc, nano, UTC)); - } - - private Value unpackDateTime(ZoneMode unpackOffset, BaselineMode useUtcBaseline) throws IOException { - var epochSecondLocal = unpacker.unpackLong(); - var nano = Math.toIntExact(unpacker.unpackLong()); - Supplier zoneIdSupplier; - if (unpackOffset == ZoneMode.OFFSET) { - var offsetSeconds = Math.toIntExact(unpacker.unpackLong()); - zoneIdSupplier = () -> ZoneOffset.ofTotalSeconds(offsetSeconds); - } else { - var zoneIdString = unpacker.unpackString(); - zoneIdSupplier = () -> ZoneId.of(zoneIdString); - } - ZoneId zoneId; - try { - zoneId = zoneIdSupplier.get(); - } catch (DateTimeException e) { - return valueFactory.unsupportedDateTimeValue(e); - } - return useUtcBaseline == BaselineMode.UTC - ? valueFactory.value(newZonedDateTimeUsingUtcBaseline(epochSecondLocal, nano, zoneId)) - : valueFactory.value(newZonedDateTime(epochSecondLocal, nano, zoneId)); - } - - private Value unpackDuration() throws IOException { - var months = unpacker.unpackLong(); - var days = unpacker.unpackLong(); - var seconds = unpacker.unpackLong(); - var nanoseconds = Math.toIntExact(unpacker.unpackLong()); - return valueFactory.isoDuration(months, days, seconds, nanoseconds); - } - - private Value unpackPoint2D() throws IOException { - var srid = Math.toIntExact(unpacker.unpackLong()); - var x = unpacker.unpackDouble(); - var y = unpacker.unpackDouble(); - return valueFactory.point(srid, x, y); - } - - private Value unpackPoint3D() throws IOException { - var srid = Math.toIntExact(unpacker.unpackLong()); - var x = unpacker.unpackDouble(); - var y = unpacker.unpackDouble(); - var z = unpacker.unpackDouble(); - return valueFactory.point(srid, x, y, z); - } - - private static ZonedDateTime newZonedDateTime(long epochSecondLocal, long nano, ZoneId zoneId) { - var instant = Instant.ofEpochSecond(epochSecondLocal, nano); - var localDateTime = LocalDateTime.ofInstant(instant, UTC); - return ZonedDateTime.of(localDateTime, zoneId); - } - - private ZonedDateTime newZonedDateTimeUsingUtcBaseline(long epochSecondLocal, int nano, ZoneId zoneId) { - var instant = Instant.ofEpochSecond(epochSecondLocal, nano); - var localDateTime = LocalDateTime.ofInstant(instant, zoneId); - return ZonedDateTime.of(localDateTime, zoneId); - } - - private BoltProtocolException instantiateExceptionForUnknownType(byte type) { - return new BoltProtocolException("Unknown struct type: " + type); - } - - protected int getNodeFields() { - return NODE_FIELDS; - } - - protected int getRelationshipFields() { - return RELATIONSHIP_FIELDS; - } - - private enum ZoneMode { - OFFSET, - ZONE_ID - } - - private enum BaselineMode { - UTC, - LEGACY - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/BeginMessageEncoder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/BeginMessageEncoder.java deleted file mode 100644 index 3cf233fb22..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/BeginMessageEncoder.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.Preconditions.checkArgument; - -import java.io.IOException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; - -public class BeginMessageEncoder implements MessageEncoder { - @Override - public void encode(Message message, ValuePacker packer, ValueFactory valueFactory) throws IOException { - checkArgument(message, BeginMessage.class); - var beginMessage = (BeginMessage) message; - packer.packStructHeader(1, beginMessage.signature()); - packer.pack(beginMessage.metadata()); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/CommitMessageEncoder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/CommitMessageEncoder.java deleted file mode 100644 index d47c1592da..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/CommitMessageEncoder.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.Preconditions.checkArgument; - -import java.io.IOException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; - -public class CommitMessageEncoder implements MessageEncoder { - @Override - public void encode(Message message, ValuePacker packer, ValueFactory valueFactory) throws IOException { - checkArgument(message, CommitMessage.class); - packer.packStructHeader(0, CommitMessage.SIGNATURE); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/DiscardAllMessageEncoder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/DiscardAllMessageEncoder.java deleted file mode 100644 index 6d13df0b27..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/DiscardAllMessageEncoder.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.Preconditions.checkArgument; - -import java.io.IOException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage; - -public class DiscardAllMessageEncoder implements MessageEncoder { - @Override - public void encode(Message message, ValuePacker packer, ValueFactory valueFactory) throws IOException { - checkArgument(message, DiscardAllMessage.class); - packer.packStructHeader(0, DiscardAllMessage.SIGNATURE); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/DiscardMessageEncoder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/DiscardMessageEncoder.java deleted file mode 100644 index 284f3f6f12..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/DiscardMessageEncoder.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.Preconditions.checkArgument; - -import java.io.IOException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardMessage; - -public class DiscardMessageEncoder implements MessageEncoder { - @Override - public void encode(Message message, ValuePacker packer, ValueFactory valueFactory) throws IOException { - checkArgument(message, DiscardMessage.class); - packer.packStructHeader(1, DiscardMessage.SIGNATURE); - packer.pack(((DiscardMessage) message).metadata()); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/GoodbyeMessageEncoder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/GoodbyeMessageEncoder.java deleted file mode 100644 index 87e56792c3..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/GoodbyeMessageEncoder.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.Preconditions.checkArgument; - -import java.io.IOException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage; - -public class GoodbyeMessageEncoder implements MessageEncoder { - @Override - public void encode(Message message, ValuePacker packer, ValueFactory valueFactory) throws IOException { - checkArgument(message, GoodbyeMessage.class); - packer.packStructHeader(0, GoodbyeMessage.SIGNATURE); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/HelloMessageEncoder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/HelloMessageEncoder.java deleted file mode 100644 index ad216c33f8..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/HelloMessageEncoder.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.Preconditions.checkArgument; - -import java.io.IOException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; - -public class HelloMessageEncoder implements MessageEncoder { - @Override - public void encode(Message message, ValuePacker packer, ValueFactory valueFactory) throws IOException { - checkArgument(message, HelloMessage.class); - var helloMessage = (HelloMessage) message; - packer.packStructHeader(1, helloMessage.signature()); - packer.pack(helloMessage.metadata()); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/LogoffMessageEncoder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/LogoffMessageEncoder.java deleted file mode 100644 index d98e1f4970..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/LogoffMessageEncoder.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.Preconditions.checkArgument; - -import java.io.IOException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.LogoffMessage; - -public class LogoffMessageEncoder implements MessageEncoder { - @Override - public void encode(Message message, ValuePacker packer, ValueFactory valueFactory) throws IOException { - checkArgument(message, LogoffMessage.class); - packer.packStructHeader(0, message.signature()); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/LogonMessageEncoder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/LogonMessageEncoder.java deleted file mode 100644 index 387d545c52..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/LogonMessageEncoder.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.Preconditions.checkArgument; - -import java.io.IOException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.LogonMessage; - -public class LogonMessageEncoder implements MessageEncoder { - @Override - public void encode(Message message, ValuePacker packer, ValueFactory valueFactory) throws IOException { - checkArgument(message, LogonMessage.class); - var logonMessage = (LogonMessage) message; - packer.packStructHeader(1, logonMessage.signature()); - packer.pack(logonMessage.metadata()); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/PullAllMessageEncoder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/PullAllMessageEncoder.java deleted file mode 100644 index 10cb3db1b4..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/PullAllMessageEncoder.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.Preconditions.checkArgument; - -import java.io.IOException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullAllMessage; - -public class PullAllMessageEncoder implements MessageEncoder { - @Override - public void encode(Message message, ValuePacker packer, ValueFactory valueFactory) throws IOException { - checkArgument(message, PullAllMessage.class); - packer.packStructHeader(0, PullAllMessage.SIGNATURE); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/PullMessageEncoder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/PullMessageEncoder.java deleted file mode 100644 index ae1a766c33..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/PullMessageEncoder.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.Preconditions.checkArgument; - -import java.io.IOException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; - -public class PullMessageEncoder implements MessageEncoder { - @Override - public void encode(Message message, ValuePacker packer, ValueFactory valueFactory) throws IOException { - checkArgument(message, PullMessage.class); - packer.packStructHeader(1, PullMessage.SIGNATURE); - packer.pack(((PullMessage) message).metadata()); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/ResetMessageEncoder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/ResetMessageEncoder.java deleted file mode 100644 index 3284f7a31f..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/ResetMessageEncoder.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.Preconditions.checkArgument; - -import java.io.IOException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage; - -public class ResetMessageEncoder implements MessageEncoder { - @Override - public void encode(Message message, ValuePacker packer, ValueFactory valueFactory) throws IOException { - checkArgument(message, ResetMessage.class); - packer.packStructHeader(0, ResetMessage.SIGNATURE); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/RollbackMessageEncoder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/RollbackMessageEncoder.java deleted file mode 100644 index d049b5715b..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/RollbackMessageEncoder.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.Preconditions.checkArgument; - -import java.io.IOException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; - -public class RollbackMessageEncoder implements MessageEncoder { - @Override - public void encode(Message message, ValuePacker packer, ValueFactory valueFactory) throws IOException { - checkArgument(message, RollbackMessage.class); - packer.packStructHeader(0, RollbackMessage.SIGNATURE); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/RouteMessageEncoder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/RouteMessageEncoder.java deleted file mode 100644 index cf9e6d95fe..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/RouteMessageEncoder.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.Preconditions.checkArgument; - -import java.io.IOException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RouteMessage; - -/** - * Encodes the ROUTE message to the stream - */ -public class RouteMessageEncoder implements MessageEncoder { - @Override - public void encode(Message message, ValuePacker packer, ValueFactory valueFactory) throws IOException { - checkArgument(message, RouteMessage.class); - var routeMessage = (RouteMessage) message; - packer.packStructHeader(3, message.signature()); - packer.pack(routeMessage.routingContext()); - packer.pack(valueFactory.value(routeMessage.bookmarks())); - packer.pack(routeMessage.databaseName()); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/RouteV44MessageEncoder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/RouteV44MessageEncoder.java deleted file mode 100644 index 661002bca1..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/RouteV44MessageEncoder.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.Preconditions.checkArgument; - -import java.io.IOException; -import java.util.Collections; -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RouteMessage; - -/** - * Encodes the ROUTE message to the stream - */ -public class RouteV44MessageEncoder implements MessageEncoder { - @Override - public void encode(Message message, ValuePacker packer, ValueFactory valueFactory) throws IOException { - checkArgument(message, RouteMessage.class); - var routeMessage = (RouteMessage) message; - packer.packStructHeader(3, message.signature()); - packer.pack(routeMessage.routingContext()); - packer.pack(valueFactory.value(routeMessage.bookmarks())); - - Map params; - if (routeMessage.impersonatedUser() != null && routeMessage.databaseName() == null) { - params = Collections.singletonMap("imp_user", valueFactory.value(routeMessage.impersonatedUser())); - } else if (routeMessage.databaseName() != null) { - params = Collections.singletonMap("db", valueFactory.value(routeMessage.databaseName())); - } else { - params = Collections.emptyMap(); - } - packer.pack(params); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/RunWithMetadataMessageEncoder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/RunWithMetadataMessageEncoder.java deleted file mode 100644 index 9757c7e4e4..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/RunWithMetadataMessageEncoder.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.Preconditions.checkArgument; - -import java.io.IOException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage; - -public class RunWithMetadataMessageEncoder implements MessageEncoder { - @Override - public void encode(Message message, ValuePacker packer, ValueFactory valueFactory) throws IOException { - checkArgument(message, RunWithMetadataMessage.class); - var runMessage = (RunWithMetadataMessage) message; - packer.packStructHeader(3, runMessage.signature()); - packer.pack(runMessage.query()); - packer.pack(runMessage.parameters()); - packer.pack(runMessage.metadata()); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/TelemetryMessageEncoder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/TelemetryMessageEncoder.java deleted file mode 100644 index 4d3ff8ae9a..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/TelemetryMessageEncoder.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.Preconditions.checkArgument; - -import java.io.IOException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.TelemetryMessage; - -public class TelemetryMessageEncoder implements MessageEncoder { - @Override - public void encode(Message message, ValuePacker packer, ValueFactory valueFactory) throws IOException { - checkArgument(message, TelemetryMessage.class); - var telemetryMessage = (TelemetryMessage) message; - packer.packStructHeader(1, TelemetryMessage.SIGNATURE); - packer.pack(valueFactory.value(telemetryMessage.api())); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/AbstractStreamingMessage.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/AbstractStreamingMessage.java deleted file mode 100644 index 5636aa2a99..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/AbstractStreamingMessage.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.MetadataExtractor.ABSENT_QUERY_ID; - -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; - -public abstract class AbstractStreamingMessage implements Message { - private final Map metadata = new HashMap<>(); - - AbstractStreamingMessage(long n, long id, ValueFactory valueFactory) { - this.metadata.put("n", valueFactory.value(n)); - if (id != ABSENT_QUERY_ID) { - this.metadata.put("qid", valueFactory.value(id)); - } - } - - public Map metadata() { - return metadata; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - var that = (AbstractStreamingMessage) o; - return Objects.equals(metadata, that.metadata); - } - - protected abstract String name(); - - @Override - public int hashCode() { - return Objects.hash(metadata); - } - - @Override - public String toString() { - return String.format("%s %s", name(), metadata); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/BeginMessage.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/BeginMessage.java deleted file mode 100644 index 2124136e9f..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/BeginMessage.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.TransactionMetadataBuilder.buildMetadata; - -import java.time.Duration; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; - -public class BeginMessage extends MessageWithMetadata { - public static final byte SIGNATURE = 0x11; - - public BeginMessage( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - DatabaseName databaseName, - AccessMode mode, - String impersonatedUser, - String txType, - NotificationConfig notificationConfig, - boolean legacyNotifications, - LoggingProvider logging, - ValueFactory valueFactory) { - this( - bookmarks, - txTimeout, - txMetadata, - mode, - databaseName, - impersonatedUser, - txType, - notificationConfig, - legacyNotifications, - logging, - valueFactory); - } - - public BeginMessage( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - AccessMode mode, - DatabaseName databaseName, - String impersonatedUser, - String txType, - NotificationConfig notificationConfig, - boolean legacyNotifications, - LoggingProvider logging, - ValueFactory valueFactory) { - super(buildMetadata( - txTimeout, - txMetadata, - databaseName, - mode, - bookmarks, - impersonatedUser, - txType, - notificationConfig, - legacyNotifications, - logging, - valueFactory)); - } - - @Override - public byte signature() { - return SIGNATURE; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - var that = (BeginMessage) o; - return Objects.equals(metadata(), that.metadata()); - } - - @Override - public int hashCode() { - return Objects.hash(metadata()); - } - - @Override - public String toString() { - return "BEGIN " + metadata(); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/CommitMessage.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/CommitMessage.java deleted file mode 100644 index 7e5a00dd87..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/CommitMessage.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request; - -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; - -public class CommitMessage implements Message { - public static final byte SIGNATURE = 0x12; - - public static final Message COMMIT = new CommitMessage(); - - private CommitMessage() {} - - @Override - public byte signature() { - return SIGNATURE; - } - - @Override - public String toString() { - return "COMMIT"; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/DiscardAllMessage.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/DiscardAllMessage.java deleted file mode 100644 index 6f2c2b2d7e..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/DiscardAllMessage.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request; - -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; - -public class DiscardAllMessage implements Message { - public static final byte SIGNATURE = 0x2F; - - public static final DiscardAllMessage DISCARD_ALL = new DiscardAllMessage(); - - private DiscardAllMessage() {} - - @Override - public byte signature() { - return SIGNATURE; - } - - @Override - public String toString() { - return "DISCARD_ALL"; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/DiscardMessage.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/DiscardMessage.java deleted file mode 100644 index 281e9de82c..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/DiscardMessage.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request; - -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; - -public class DiscardMessage extends AbstractStreamingMessage { - public static final byte SIGNATURE = 0x2F; - - public DiscardMessage(long n, long id, ValueFactory valueFactory) { - super(n, id, valueFactory); - } - - @Override - protected String name() { - return "DISCARD"; - } - - @Override - public byte signature() { - return SIGNATURE; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/GoodbyeMessage.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/GoodbyeMessage.java deleted file mode 100644 index da29e1c3d0..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/GoodbyeMessage.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request; - -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; - -public class GoodbyeMessage implements Message { - public static final byte SIGNATURE = 0x02; - - public static final GoodbyeMessage GOODBYE = new GoodbyeMessage(); - - private GoodbyeMessage() {} - - @Override - public byte signature() { - return SIGNATURE; - } - - @Override - public String toString() { - return "GOODBYE"; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/HelloMessage.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/HelloMessage.java deleted file mode 100644 index fea034ff9a..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/HelloMessage.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import org.neo4j.driver.internal.bolt.api.BoltAgent; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; - -public class HelloMessage extends MessageWithMetadata { - public static final byte SIGNATURE = 0x01; - - private static final String USER_AGENT_METADATA_KEY = "user_agent"; - private static final String BOLT_AGENT_METADATA_KEY = "bolt_agent"; - private static final String BOLT_AGENT_PRODUCT_KEY = "product"; - private static final String BOLT_AGENT_PLATFORM_KEY = "platform"; - private static final String BOLT_AGENT_LANGUAGE_KEY = "language"; - private static final String BOLT_AGENT_LANGUAGE_DETAIL_KEY = "language_details"; - private static final String ROUTING_CONTEXT_METADATA_KEY = "routing"; - private static final String PATCH_BOLT_METADATA_KEY = "patch_bolt"; - private static final String CREDENTIALS_KEY = "credentials"; - - private static final String DATE_TIME_UTC_PATCH_VALUE = "utc"; - - private final ValueFactory valueFactory; - - public HelloMessage( - String userAgent, - BoltAgent boltAgent, - Map authMap, - Map routingContext, - boolean includeDateTimeUtc, - NotificationConfig notificationConfig, - boolean legacyNotifications, - ValueFactory valueFactory) { - super(buildMetadata( - userAgent, - boltAgent, - authMap, - routingContext, - includeDateTimeUtc, - notificationConfig, - legacyNotifications, - valueFactory)); - this.valueFactory = Objects.requireNonNull(valueFactory); - } - - @Override - public byte signature() { - return SIGNATURE; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - var that = (HelloMessage) o; - return Objects.equals(metadata(), that.metadata()); - } - - @Override - public int hashCode() { - return Objects.hash(metadata()); - } - - @Override - public String toString() { - Map metadataCopy = new HashMap<>(metadata()); - metadataCopy.replace(CREDENTIALS_KEY, valueFactory.value("******")); - return "HELLO " + metadataCopy; - } - - private static Map buildMetadata( - String userAgent, - BoltAgent boltAgent, - Map authMap, - Map routingContext, - boolean includeDateTimeUtc, - NotificationConfig notificationConfig, - boolean legacyNotifications, - ValueFactory valueFactory) { - Map result = new HashMap<>(); - for (var entry : authMap.entrySet()) { - result.put(entry.getKey(), valueFactory.value(entry.getValue())); - } - if (userAgent != null) { - result.put(USER_AGENT_METADATA_KEY, valueFactory.value(userAgent)); - } - if (boltAgent != null) { - var boltAgentMap = toMap(boltAgent); - result.put(BOLT_AGENT_METADATA_KEY, valueFactory.value(boltAgentMap)); - } - if (routingContext != null) { - result.put(ROUTING_CONTEXT_METADATA_KEY, valueFactory.value(routingContext)); - } - if (includeDateTimeUtc) { - result.put(PATCH_BOLT_METADATA_KEY, valueFactory.value(Collections.singleton(DATE_TIME_UTC_PATCH_VALUE))); - } - MessageWithMetadata.appendNotificationConfig(result, notificationConfig, legacyNotifications, valueFactory); - return result; - } - - private static HashMap toMap(BoltAgent boltAgent) { - var boltAgentMap = new HashMap(); - boltAgentMap.put(BOLT_AGENT_PRODUCT_KEY, boltAgent.product()); - if (boltAgent.platform() != null) { - boltAgentMap.put(BOLT_AGENT_PLATFORM_KEY, boltAgent.platform()); - } - if (boltAgent.language() != null) { - boltAgentMap.put(BOLT_AGENT_LANGUAGE_KEY, boltAgent.language()); - } - if (boltAgent.languageDetails() != null) { - boltAgentMap.put(BOLT_AGENT_LANGUAGE_DETAIL_KEY, boltAgent.languageDetails()); - } - return boltAgentMap; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/LogoffMessage.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/LogoffMessage.java deleted file mode 100644 index c07dd60378..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/LogoffMessage.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request; - -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; - -public class LogoffMessage implements Message { - public static final byte SIGNATURE = 0x6B; - - public static final LogoffMessage INSTANCE = new LogoffMessage(); - - private LogoffMessage() {} - - @Override - public byte signature() { - return SIGNATURE; - } - - @Override - public String toString() { - return "LOGOFF"; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/LogonMessage.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/LogonMessage.java deleted file mode 100644 index bd78b83dc0..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/LogonMessage.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request; - -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; - -public class LogonMessage extends MessageWithMetadata { - public static final byte SIGNATURE = 0x6A; - private static final String CREDENTIALS_KEY = "credentials"; - - private final ValueFactory valueFactory; - - public LogonMessage(Map authMap, ValueFactory valueFactory) { - super(authMap); - this.valueFactory = Objects.requireNonNull(valueFactory); - } - - @Override - public byte signature() { - return SIGNATURE; - } - - @Override - public String toString() { - Map metadataCopy = new HashMap<>(metadata()); - metadataCopy.replace(CREDENTIALS_KEY, valueFactory.value("******")); - return "LOGON " + metadataCopy; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/MessageWithMetadata.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/MessageWithMetadata.java deleted file mode 100644 index de03325f40..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/MessageWithMetadata.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request; - -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.NotificationClassification; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; - -abstract class MessageWithMetadata implements Message { - static final String NOTIFICATIONS_MINIMUM_SEVERITY = "notifications_minimum_severity"; - static final String NOTIFICATIONS_DISABLED_CATEGORIES = "notifications_disabled_categories"; - static final String NOTIFICATIONS_DISABLED_CLASSIFICATIONS = "notifications_disabled_classifications"; - private final Map metadata; - - public MessageWithMetadata(Map metadata) { - this.metadata = metadata; - } - - public Map metadata() { - return metadata; - } - - static void appendNotificationConfig( - Map result, - NotificationConfig config, - boolean legacyNotifications, - ValueFactory valueFactory) { - if (config != null) { - var severity = config.minimumSeverity(); - if (severity != null) { - result.put( - NOTIFICATIONS_MINIMUM_SEVERITY, - valueFactory.value(severity.type().toString())); - } - var disabledClassifications = config.disabledClassifications(); - if (disabledClassifications != null) { - var list = disabledClassifications.stream() - .map(NotificationClassification::type) - .map(Enum::toString) - .toList(); - result.put( - legacyNotifications - ? NOTIFICATIONS_DISABLED_CATEGORIES - : NOTIFICATIONS_DISABLED_CLASSIFICATIONS, - valueFactory.value(list)); - } - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/MultiDatabaseUtil.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/MultiDatabaseUtil.java deleted file mode 100644 index d55b663e6a..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/MultiDatabaseUtil.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request; - -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.exception.BoltClientException; - -public final class MultiDatabaseUtil { - public static void assertEmptyDatabaseName(DatabaseName databaseName, BoltProtocolVersion boltVersion) { - if (databaseName.databaseName().isPresent()) { - throw new BoltClientException(String.format( - "Database name parameter for selecting database is not supported in Bolt Protocol Version %s. " - + "Database name: '%s'", - boltVersion, databaseName.description())); - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/PullAllMessage.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/PullAllMessage.java deleted file mode 100644 index ff85872147..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/PullAllMessage.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request; - -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; - -/** - * PULL_ALL request message - *

- * Sent by clients to pull the entirety of the remaining stream down. - */ -public class PullAllMessage implements Message { - public static final byte SIGNATURE = 0x3F; - - public static final PullAllMessage PULL_ALL = new PullAllMessage(); - - private PullAllMessage() {} - - @Override - public byte signature() { - return SIGNATURE; - } - - @Override - public String toString() { - return "PULL_ALL"; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/PullMessage.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/PullMessage.java deleted file mode 100644 index 8690fc549a..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/PullMessage.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request; - -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; - -/** - * PULL request message - *

- * Sent by clients to pull the entirety of the remaining stream down. - */ -public class PullMessage extends AbstractStreamingMessage { - public static final byte SIGNATURE = 0x3F; - - public PullMessage(long n, long id, ValueFactory valueFactory) { - super(n, id, valueFactory); - } - - @Override - protected String name() { - return "PULL"; - } - - @Override - public byte signature() { - return SIGNATURE; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/ResetMessage.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/ResetMessage.java deleted file mode 100644 index 59f5b35ea3..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/ResetMessage.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request; - -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; - -/** - * RESET request message - *

- * Sent by clients to reset a session to a clean state - closing any open transaction or result streams. - * This also acknowledges receipt of failures sent by the server. This is required to - * allow optimistic sending of multiple messages before responses have been received - pipelining. - *

- * When something goes wrong, we want the server to stop processing our already sent messages, - * but the server cannot tell the difference between what was sent before and after we saw the - * error. - *

- * This message acts as a barrier after an error, informing the server that we've seen the error - * message, and that messages that follow this one are safe to execute. - */ -public class ResetMessage implements Message { - public static final byte SIGNATURE = 0x0F; - - public static final ResetMessage RESET = new ResetMessage(); - - private ResetMessage() {} - - @Override - public byte signature() { - return SIGNATURE; - } - - @Override - public String toString() { - return "RESET"; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/RollbackMessage.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/RollbackMessage.java deleted file mode 100644 index a60197b6d6..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/RollbackMessage.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request; - -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; - -public class RollbackMessage implements Message { - public static final byte SIGNATURE = 0x13; - - public static final Message ROLLBACK = new RollbackMessage(); - - private RollbackMessage() {} - - @Override - public byte signature() { - return SIGNATURE; - } - - @Override - public String toString() { - return "ROLLBACK"; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/RouteMessage.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/RouteMessage.java deleted file mode 100644 index 01f3aeca64..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/RouteMessage.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request; - -import static java.util.Collections.unmodifiableMap; - -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; - -/** - * From the application point of view it is not interesting to know about the role a member plays in the cluster. Instead, the application needs to know which - * instance can provide the wanted service. - *

- * This message is used to fetch this routing information. - */ -public record RouteMessage( - Map routingContext, Set bookmarks, String databaseName, String impersonatedUser) - implements Message { - public static final byte SIGNATURE = 0x66; - - /** - * Constructor - * - * @param routingContext The routing context used to define the routing table. Multi-datacenter deployments is one of its use cases. - * @param bookmarks The bookmarks used when getting the routing table. - * @param databaseName The name of the database to get the routing table for. - * @param impersonatedUser The name of the impersonated user to get the routing table for, should be {@code null} for non-impersonated requests - */ - public RouteMessage( - Map routingContext, Set bookmarks, String databaseName, String impersonatedUser) { - this.routingContext = unmodifiableMap(routingContext); - this.bookmarks = bookmarks; - this.databaseName = databaseName; - this.impersonatedUser = impersonatedUser; - } - - @Override - public byte signature() { - return SIGNATURE; - } - - @Override - public String toString() { - return String.format("ROUTE %s %s %s %s", routingContext, bookmarks, databaseName, impersonatedUser); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - var that = (RouteMessage) o; - return routingContext.equals(that.routingContext) - && Objects.equals(databaseName, that.databaseName) - && Objects.equals(impersonatedUser, that.impersonatedUser); - } - - @Override - public int hashCode() { - return Objects.hash(routingContext, databaseName, impersonatedUser); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/RunWithMetadataMessage.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/RunWithMetadataMessage.java deleted file mode 100644 index 592643c180..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/RunWithMetadataMessage.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request; - -import static java.util.Collections.emptyMap; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.TransactionMetadataBuilder.buildMetadata; - -import java.time.Duration; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; - -public class RunWithMetadataMessage extends MessageWithMetadata { - public static final byte SIGNATURE = 0x10; - - private final String query; - private final Map parameters; - - public static RunWithMetadataMessage autoCommitTxRunMessage( - String query, - Map parameters, - Duration txTimeout, - Map txMetadata, - DatabaseName databaseName, - AccessMode mode, - Set bookmarks, - String impersonatedUser, - NotificationConfig notificationConfig, - boolean legacyNotifications, - LoggingProvider logging, - ValueFactory valueFactory) { - var metadata = buildMetadata( - txTimeout, - txMetadata, - databaseName, - mode, - bookmarks, - impersonatedUser, - null, - notificationConfig, - legacyNotifications, - logging, - valueFactory); - return new RunWithMetadataMessage(query, parameters, metadata); - } - - public static RunWithMetadataMessage unmanagedTxRunMessage(String query, Map parameters) { - return new RunWithMetadataMessage(query, parameters, emptyMap()); - } - - private RunWithMetadataMessage(String query, Map parameters, Map metadata) { - super(metadata); - this.query = query; - this.parameters = parameters; - } - - public String query() { - return query; - } - - public Map parameters() { - return parameters; - } - - @Override - public byte signature() { - return SIGNATURE; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - var that = (RunWithMetadataMessage) o; - return Objects.equals(query, that.query) - && Objects.equals(parameters, that.parameters) - && Objects.equals(metadata(), that.metadata()); - } - - @Override - public int hashCode() { - return Objects.hash(query, parameters, metadata()); - } - - @Override - public String toString() { - return "RUN \"" + query + "\" " + parameters + " " + metadata(); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/TelemetryMessage.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/TelemetryMessage.java deleted file mode 100644 index fa43367bb5..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/TelemetryMessage.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request; - -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; - -/** - * TELEMETRY message - * Sent by the client to inform which API is used. - * - * @param api the API identification on the protocol level - */ -public record TelemetryMessage(Integer api) implements Message { - public static final byte SIGNATURE = 0x54; - - @Override - public byte signature() { - return SIGNATURE; - } - - @Override - public String toString() { - return String.format("TELEMETRY %S", api); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/TransactionMetadataBuilder.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/TransactionMetadataBuilder.java deleted file mode 100644 index b52626b87b..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/TransactionMetadataBuilder.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request; - -import static java.util.Collections.emptyMap; - -import java.time.Duration; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; - -public class TransactionMetadataBuilder { - private static final String BOOKMARKS_METADATA_KEY = "bookmarks"; - private static final String DATABASE_NAME_KEY = "db"; - private static final String TX_TIMEOUT_METADATA_KEY = "tx_timeout"; - private static final String TX_METADATA_METADATA_KEY = "tx_metadata"; - private static final String MODE_KEY = "mode"; - private static final String MODE_READ_VALUE = "r"; - private static final String IMPERSONATED_USER_KEY = "imp_user"; - private static final String TX_TYPE_KEY = "tx_type"; - - public static Map buildMetadata( - Duration txTimeout, - Map txMetadata, - DatabaseName databaseName, - AccessMode mode, - Set bookmarks, - String impersonatedUser, - String txType, - NotificationConfig notificationConfig, - boolean legacyNotifications, - LoggingProvider logging, - ValueFactory valueFactory) { - var bookmarksPresent = !bookmarks.isEmpty(); - var txTimeoutPresent = txTimeout != null; - var txMetadataPresent = txMetadata != null && !txMetadata.isEmpty(); - var accessModePresent = mode == AccessMode.READ; - var databaseNamePresent = databaseName.databaseName().isPresent(); - var impersonatedUserPresent = impersonatedUser != null; - var txTypePresent = txType != null; - var notificationConfigPresent = notificationConfig != null; - - if (!bookmarksPresent - && !txTimeoutPresent - && !txMetadataPresent - && !accessModePresent - && !databaseNamePresent - && !impersonatedUserPresent - && !txTypePresent - && !notificationConfigPresent) { - return emptyMap(); - } - - Map result = new HashMap<>(5); - - if (bookmarksPresent) { - result.put(BOOKMARKS_METADATA_KEY, valueFactory.value(bookmarks)); - } - if (txTimeoutPresent) { - var millis = txTimeout.toMillis(); - if (txTimeout.toNanosPart() % 1_000_000 > 0) { - var log = logging.getLog(TransactionMetadataBuilder.class); - millis++; - log.log( - System.Logger.Level.INFO, - "The transaction timeout has been rounded up to next millisecond value since the config had a fractional millisecond value"); - } - result.put(TX_TIMEOUT_METADATA_KEY, valueFactory.value(millis)); - } - if (txMetadataPresent) { - result.put(TX_METADATA_METADATA_KEY, valueFactory.value(txMetadata)); - } - if (accessModePresent) { - result.put(MODE_KEY, valueFactory.value(MODE_READ_VALUE)); - } - if (impersonatedUserPresent) { - result.put(IMPERSONATED_USER_KEY, valueFactory.value(impersonatedUser)); - } - if (txTypePresent) { - result.put(TX_TYPE_KEY, valueFactory.value(txType)); - } - MessageWithMetadata.appendNotificationConfig(result, notificationConfig, legacyNotifications, valueFactory); - - databaseName.databaseName().ifPresent(name -> result.put(DATABASE_NAME_KEY, valueFactory.value(name))); - - return result; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/response/FailureMessage.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/response/FailureMessage.java deleted file mode 100644 index 40e40d76fe..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/response/FailureMessage.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response; - -import static java.lang.String.format; - -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; - -/** - * FAILURE response message - *

- * Sent by the server to signal a failed operation. - * Terminates response sequence. - */ -public record FailureMessage(String code, String message) implements Message { - public static final byte SIGNATURE = 0x7F; - - @Override - public byte signature() { - return SIGNATURE; - } - - @Override - public String toString() { - return format("FAILURE %s \"%s\"", code, message); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/response/IgnoredMessage.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/response/IgnoredMessage.java deleted file mode 100644 index 705a605d96..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/response/IgnoredMessage.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response; - -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; - -/** - * IGNORED response message - *

- * Sent by the server to signal that an operation has been ignored. - * Terminates response sequence. - */ -public class IgnoredMessage implements Message { - public static final byte SIGNATURE = 0x7E; - - public static final IgnoredMessage IGNORED = new IgnoredMessage(); - - private IgnoredMessage() {} - - @Override - public byte signature() { - return SIGNATURE; - } - - @Override - public String toString() { - return "IGNORED {}"; - } - - @Override - public boolean equals(Object obj) { - return obj != null && obj.getClass() == getClass(); - } - - @Override - public int hashCode() { - return 1; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/response/RecordMessage.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/response/RecordMessage.java deleted file mode 100644 index caf98c190b..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/response/RecordMessage.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response; - -import java.util.Arrays; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; - -public record RecordMessage(Value[] fields) implements Message { - public static final byte SIGNATURE = 0x71; - - @Override - public byte signature() { - return SIGNATURE; - } - - @Override - public String toString() { - return "RECORD " + Arrays.toString(fields); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - var that = (RecordMessage) o; - - return Arrays.equals(fields, that.fields); - } - - @Override - public int hashCode() { - return Arrays.hashCode(fields); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/response/SuccessMessage.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/response/SuccessMessage.java deleted file mode 100644 index d400b548a2..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/response/SuccessMessage.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response; - -import static java.lang.String.format; - -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; - -/** - * SUCCESS response message - *

- * Sent by the server to signal a successful operation. - * Terminates response sequence. - */ -public record SuccessMessage(Map metadata) implements Message { - public static final byte SIGNATURE = 0x70; - - @Override - public byte signature() { - return SIGNATURE; - } - - @Override - public String toString() { - return format("SUCCESS %s", metadata); - } - - @Override - public boolean equals(Object obj) { - return obj != null && obj.getClass() == getClass(); - } - - @Override - public int hashCode() { - return 1; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v3/BoltProtocolV3.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v3/BoltProtocolV3.java deleted file mode 100644 index c5349504e6..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v3/BoltProtocolV3.java +++ /dev/null @@ -1,456 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.messageDispatcher; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage.COMMIT; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage.ROLLBACK; - -import io.netty.channel.Channel; -import java.time.Clock; -import java.time.Duration; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.BoltAgent; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.ClusterComposition; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.DatabaseNameUtil; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.exception.BoltException; -import org.neo4j.driver.internal.bolt.api.exception.BoltUnsupportedFeatureException; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.DiscardSummary; -import org.neo4j.driver.internal.bolt.api.summary.PullSummary; -import org.neo4j.driver.internal.bolt.api.summary.RouteSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.BeginTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.CommitTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.DiscardResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.HelloResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.PullResponseHandlerImpl; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.ResetResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RollbackTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RunResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.PullMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.MultiDatabaseUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullAllMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.MetadataExtractor; - -public class BoltProtocolV3 implements BoltProtocol { - public static final BoltProtocolVersion VERSION = new BoltProtocolVersion(3, 0); - - public static final BoltProtocol INSTANCE = new BoltProtocolV3(); - - public static final MetadataExtractor METADATA_EXTRACTOR = new MetadataExtractor("t_first"); - - private static final String ROUTING_CONTEXT = "context"; - private static final String GET_ROUTING_TABLE = - "CALL dbms.cluster.routing.getRoutingTable($" + ROUTING_CONTEXT + ")"; - - @Override - public MessageFormat createMessageFormat() { - return new MessageFormatV3(); - } - - @Override - public CompletionStage initializeChannel( - Channel channel, - String userAgent, - BoltAgent boltAgent, - Map authMap, - RoutingContext routingContext, - NotificationConfig notificationConfig, - Clock clock, - CompletableFuture latestAuthMillisFuture, - ValueFactory valueFactory) { - var exception = verifyNotificationConfigSupported(notificationConfig); - if (exception != null) { - return CompletableFuture.failedStage(exception); - } - HelloMessage message; - - if (routingContext.isServerRoutingEnabled()) { - message = new HelloMessage( - userAgent, - null, - authMap, - routingContext.toMap(), - includeDateTimeUtcPatchInHello(), - notificationConfig, - useLegacyNotifications(), - valueFactory); - } else { - message = new HelloMessage( - userAgent, - null, - authMap, - null, - includeDateTimeUtcPatchInHello(), - notificationConfig, - useLegacyNotifications(), - valueFactory); - } - - var future = new CompletableFuture(); - var handler = new HelloResponseHandler(future, channel, clock, latestAuthMillisFuture); - messageDispatcher(channel).enqueue(handler); - channel.writeAndFlush(message, channel.voidPromise()); - return future.thenApply(ignored -> channel); - } - - @SuppressWarnings("DuplicatedCode") - @Override - public CompletionStage route( - Connection connection, - Map routingContext, - Set bookmarks, - String databaseName, - String impersonatedUser, - MessageHandler handler, - Clock clock, - LoggingProvider logging, - ValueFactory valueFactory) { - var query = new Query(GET_ROUTING_TABLE, Map.of(ROUTING_CONTEXT, valueFactory.value(routingContext))); - - var runMessage = RunWithMetadataMessage.autoCommitTxRunMessage( - query.query(), - query.parameters(), - null, - Collections.emptyMap(), - DatabaseNameUtil.defaultDatabase(), - AccessMode.WRITE, - Collections.emptySet(), - null, - NotificationConfig.defaultConfig(), - useLegacyNotifications(), - logging, - valueFactory); - var runFuture = new CompletableFuture(); - var runHandler = new RunResponseHandler(runFuture, METADATA_EXTRACTOR); - var pullFuture = new CompletableFuture>(); - - runFuture - .thenCompose(ignored -> pullFuture) - .thenApply(map -> { - var ttl = map.get("ttl").asLong(); - var expirationTimestamp = clock.millis() + ttl * 1000; - if (ttl < 0 || ttl >= Long.MAX_VALUE / 1000L || expirationTimestamp < 0) { - expirationTimestamp = Long.MAX_VALUE; - } - - Set readers = new LinkedHashSet<>(); - Set writers = new LinkedHashSet<>(); - Set routers = new LinkedHashSet<>(); - - for (var serversMap : map.get("servers").values()) { - var role = serversMap.get("role").asString(); - for (var server : serversMap.get("addresses").values()) { - var address = new BoltServerAddress(server.asString()); - switch (role) { - case "WRITE" -> writers.add(address); - case "READ" -> readers.add(address); - case "ROUTE" -> routers.add(address); - } - } - } - var db = map.get("db"); - String name = null; - if (db != null && !db.isNull()) { - name = db.asString(); - } - - var clusterComposition = - new ClusterComposition(expirationTimestamp, readers, writers, routers, name); - return new RouteSummaryImpl(clusterComposition); - }) - .whenComplete((summary, throwable) -> { - if (throwable != null) { - handler.onError(throwable); - } else { - handler.onSummary(summary); - } - }); - - return connection.write(runMessage, runHandler).thenCompose(ignored -> { - var pullMessage = PullAllMessage.PULL_ALL; - var pullHandler = new PullResponseHandlerImpl( - new PullMessageHandler() { - private Map routingTable; - - @Override - public void onRecord(Value[] fields) { - if (routingTable == null) { - var keys = runFuture.join().keys(); - routingTable = new HashMap<>(keys.size()); - for (var i = 0; i < keys.size(); i++) { - routingTable.put(keys.get(i), fields[i]); - } - routingTable = Collections.unmodifiableMap(routingTable); - } - } - - @Override - public void onError(Throwable throwable) { - pullFuture.completeExceptionally(throwable); - } - - @Override - public void onSummary(PullSummary success) { - pullFuture.complete(routingTable); - } - }, - valueFactory); - return connection.write(pullMessage, pullHandler); - }); - } - - @Override - public CompletionStage beginTransaction( - Connection connection, - DatabaseName databaseName, - AccessMode accessMode, - String impersonatedUser, - Set bookmarks, - Duration txTimeout, - Map txMetadata, - String txType, - NotificationConfig notificationConfig, - MessageHandler handler, - LoggingProvider logging, - ValueFactory valueFactory) { - var exception = verifyNotificationConfigSupported(notificationConfig); - if (exception != null) { - return CompletableFuture.failedStage(exception); - } - try { - verifyDatabaseNameBeforeTransaction(databaseName); - } catch (Exception error) { - return CompletableFuture.failedFuture(error); - } - - var beginTxFuture = new CompletableFuture(); - var beginMessage = new BeginMessage( - bookmarks, - txTimeout, - txMetadata, - databaseName, - accessMode, - impersonatedUser, - txType, - notificationConfig, - useLegacyNotifications(), - logging, - valueFactory); - beginTxFuture.whenComplete((summary, throwable) -> { - if (throwable != null) { - handler.onError(throwable); - } else { - handler.onSummary(summary); - } - }); - return connection.write(beginMessage, new BeginTxResponseHandler(beginTxFuture)); - } - - @Override - public CompletionStage commitTransaction(Connection connection, MessageHandler handler) { - var commitFuture = new CompletableFuture(); - commitFuture.whenComplete((bookmark, throwable) -> { - if (throwable != null) { - handler.onError(throwable); - } else { - handler.onSummary(bookmark); - } - }); - return connection.write(COMMIT, new CommitTxResponseHandler(commitFuture)); - } - - @Override - public CompletionStage rollbackTransaction(Connection connection, MessageHandler handler) { - var rollbackFuture = new CompletableFuture(); - rollbackFuture.whenComplete((ignored, throwable) -> { - if (throwable != null) { - handler.onError(throwable); - } else { - handler.onSummary(null); - } - }); - return connection.write(ROLLBACK, new RollbackTxResponseHandler(rollbackFuture)); - } - - @Override - public CompletionStage reset(Connection connection, MessageHandler handler) { - var resetFuture = new CompletableFuture(); - resetFuture.whenComplete((ignored, throwable) -> { - if (throwable != null) { - handler.onError(throwable); - } else { - handler.onSummary(null); - } - }); - var resetHandler = new ResetResponseHandler(resetFuture); - return connection.write(ResetMessage.RESET, resetHandler); - } - - @Override - public CompletionStage telemetry(Connection connection, Integer api, MessageHandler handler) { - return CompletableFuture.failedStage(new BoltUnsupportedFeatureException("telemetry not supported")); - } - - @SuppressWarnings("DuplicatedCode") - @Override - public CompletionStage runAuto( - Connection connection, - DatabaseName databaseName, - AccessMode accessMode, - String impersonatedUser, - String query, - Map parameters, - Set bookmarks, - Duration txTimeout, - Map txMetadata, - NotificationConfig notificationConfig, - MessageHandler handler, - LoggingProvider logging, - ValueFactory valueFactory) { - try { - verifyDatabaseNameBeforeTransaction(databaseName); - } catch (Exception error) { - return CompletableFuture.failedFuture(error); - } - - var runMessage = RunWithMetadataMessage.autoCommitTxRunMessage( - query, - parameters, - txTimeout, - txMetadata, - databaseName, - accessMode, - bookmarks, - impersonatedUser, - notificationConfig, - useLegacyNotifications(), - logging, - valueFactory); - var runFuture = new CompletableFuture(); - runFuture.whenComplete((summary, throwable) -> { - if (throwable != null) { - handler.onError(throwable); - } else { - handler.onSummary(summary); - } - }); - var runHandler = new RunResponseHandler(runFuture, METADATA_EXTRACTOR); - return connection.write(runMessage, runHandler); - } - - @SuppressWarnings("DuplicatedCode") - @Override - public CompletionStage run( - Connection connection, String query, Map parameters, MessageHandler handler) { - var runMessage = RunWithMetadataMessage.unmanagedTxRunMessage(query, parameters); - var runFuture = new CompletableFuture(); - runFuture.whenComplete((summary, throwable) -> { - if (throwable != null) { - handler.onError(throwable); - } else { - handler.onSummary(summary); - } - }); - var runHandler = new RunResponseHandler(runFuture, METADATA_EXTRACTOR); - return connection.write(runMessage, runHandler); - } - - @Override - public CompletionStage pull( - Connection connection, long qid, long request, PullMessageHandler handler, ValueFactory valueFactory) { - var pullMessage = PullAllMessage.PULL_ALL; - var pullHandler = new PullResponseHandlerImpl(handler, valueFactory); - return connection.write(pullMessage, pullHandler); - } - - @Override - public CompletionStage discard( - Connection connection, - long qid, - long number, - MessageHandler handler, - ValueFactory valueFactory) { - var discardMessage = new DiscardMessage(number, qid, valueFactory); - var discardFuture = new CompletableFuture(); - discardFuture.whenComplete((ignored, throwable) -> { - if (throwable != null) { - handler.onError(throwable); - } else { - handler.onSummary(ignored); - } - }); - var discardHandler = new DiscardResponseHandler(discardFuture); - return connection.write(discardMessage, discardHandler); - } - - protected void verifyDatabaseNameBeforeTransaction(DatabaseName databaseName) { - MultiDatabaseUtil.assertEmptyDatabaseName(databaseName, version()); - } - - @Override - public BoltProtocolVersion version() { - return VERSION; - } - - protected boolean includeDateTimeUtcPatchInHello() { - return false; - } - - protected BoltException verifyNotificationConfigSupported(NotificationConfig notificationConfig) { - BoltException exception = null; - if (notificationConfig != null && !notificationConfig.equals(NotificationConfig.defaultConfig())) { - exception = new BoltUnsupportedFeatureException(String.format( - "Notification configuration is not supported on Bolt %s", - version().toString())); - } - return exception; - } - - protected boolean useLegacyNotifications() { - return true; - } - - private record RouteSummaryImpl(ClusterComposition clusterComposition) implements RouteSummary {} - - public record Query(String query, Map parameters) {} -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v3/MessageFormatV3.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v3/MessageFormatV3.java deleted file mode 100644 index 18898e51fe..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v3/MessageFormatV3.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3; - -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonMessageReader; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -public class MessageFormatV3 implements MessageFormat { - @Override - public Writer newWriter(PackOutput output, ValueFactory valueFactory) { - return new MessageWriterV3(output, valueFactory); - } - - @Override - public Reader newReader(PackInput input, ValueFactory valueFactory) { - return new CommonMessageReader(input, false, valueFactory); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v3/MessageWriterV3.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v3/MessageWriterV3.java deleted file mode 100644 index 6c4e313f07..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v3/MessageWriterV3.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3; - -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.AbstractMessageWriter; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.BeginMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.CommitMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.DiscardAllMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.GoodbyeMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.HelloMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.PullAllMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.ResetMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.RollbackMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.RunWithMetadataMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullAllMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -public class MessageWriterV3 extends AbstractMessageWriter { - public MessageWriterV3(PackOutput output, ValueFactory valueFactory) { - super(new CommonValuePacker(output, false), buildEncoders(), valueFactory); - } - - private static Map buildEncoders() { - return Map.of( - HelloMessage.SIGNATURE, new HelloMessageEncoder(), - GoodbyeMessage.SIGNATURE, new GoodbyeMessageEncoder(), - RunWithMetadataMessage.SIGNATURE, new RunWithMetadataMessageEncoder(), - DiscardAllMessage.SIGNATURE, new DiscardAllMessageEncoder(), - PullAllMessage.SIGNATURE, new PullAllMessageEncoder(), - BeginMessage.SIGNATURE, new BeginMessageEncoder(), - CommitMessage.SIGNATURE, new CommitMessageEncoder(), - RollbackMessage.SIGNATURE, new RollbackMessageEncoder(), - ResetMessage.SIGNATURE, new ResetMessageEncoder()); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v4/BoltProtocolV4.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v4/BoltProtocolV4.java deleted file mode 100644 index 2e78a0935c..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v4/BoltProtocolV4.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v4; - -import java.time.Clock; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.ClusterComposition; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.DatabaseNameUtil; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.summary.PullSummary; -import org.neo4j.driver.internal.bolt.api.summary.RouteSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.PullResponseHandlerImpl; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RunResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.PullMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3.BoltProtocolV3; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public class BoltProtocolV4 extends BoltProtocolV3 { - public static final BoltProtocolVersion VERSION = new BoltProtocolVersion(4, 0); - public static final BoltProtocol INSTANCE = new BoltProtocolV4(); - private static final String ROUTING_CONTEXT = "context"; - private static final String DATABASE_NAME = "database"; - private static final String MULTI_DB_GET_ROUTING_TABLE = - String.format("CALL dbms.routing.getRoutingTable($%s, $%s)", ROUTING_CONTEXT, DATABASE_NAME); - - @Override - public MessageFormat createMessageFormat() { - return new MessageFormatV4(); - } - - @SuppressWarnings("DuplicatedCode") - @Override - public CompletionStage route( - Connection connection, - Map routingContext, - Set bookmarks, - String databaseName, - String impersonatedUser, - MessageHandler handler, - Clock clock, - LoggingProvider logging, - ValueFactory valueFactory) { - var query = new Query( - MULTI_DB_GET_ROUTING_TABLE, - Map.of( - ROUTING_CONTEXT, - valueFactory.value(routingContext), - DATABASE_NAME, - valueFactory.value(databaseName))); - - var runMessage = RunWithMetadataMessage.autoCommitTxRunMessage( - query.query(), - query.parameters(), - null, - Collections.emptyMap(), - DatabaseNameUtil.database("system"), - AccessMode.READ, - bookmarks, - null, - NotificationConfig.defaultConfig(), - useLegacyNotifications(), - logging, - valueFactory); - var runFuture = new CompletableFuture(); - var runHandler = new RunResponseHandler(runFuture, METADATA_EXTRACTOR); - var pullFuture = new CompletableFuture>(); - - runFuture - .thenCompose(ignored -> pullFuture) - .thenApply(map -> { - var ttl = map.get("ttl").asLong(); - var expirationTimestamp = clock.millis() + ttl * 1000; - if (ttl < 0 || ttl >= Long.MAX_VALUE / 1000L || expirationTimestamp < 0) { - expirationTimestamp = Long.MAX_VALUE; - } - - Set readers = new LinkedHashSet<>(); - Set writers = new LinkedHashSet<>(); - Set routers = new LinkedHashSet<>(); - - for (var serversMap : map.get("servers").values()) { - var role = serversMap.get("role").asString(); - for (var server : serversMap.get("addresses").values()) { - var address = new BoltServerAddress(server.asString()); - switch (role) { - case "WRITE" -> writers.add(address); - case "READ" -> readers.add(address); - case "ROUTE" -> routers.add(address); - } - } - } - var db = map.get("db"); - String name = null; - if (db != null && !db.isNull()) { - name = db.asString(); - } - - var clusterComposition = - new ClusterComposition(expirationTimestamp, readers, writers, routers, name); - return new RouteSummaryImpl(clusterComposition); - }) - .whenComplete((summary, throwable) -> { - if (throwable != null) { - handler.onError(throwable); - } else { - handler.onSummary(summary); - } - }); - - return connection.write(runMessage, runHandler).thenCompose(ignored -> { - var pullMessage = new PullMessage(-1, -1, valueFactory); - var pullHandler = new PullResponseHandlerImpl( - new PullMessageHandler() { - private Map routingTable; - - @Override - public void onRecord(Value[] fields) { - if (routingTable == null) { - var keys = runFuture.join().keys(); - routingTable = new HashMap<>(keys.size()); - for (var i = 0; i < keys.size(); i++) { - routingTable.put(keys.get(i), fields[i]); - } - routingTable = Collections.unmodifiableMap(routingTable); - } - } - - @Override - public void onError(Throwable throwable) { - pullFuture.completeExceptionally(throwable); - } - - @Override - public void onSummary(PullSummary success) { - pullFuture.complete(routingTable); - } - }, - valueFactory); - return connection.write(pullMessage, pullHandler); - }); - } - - @Override - public CompletionStage pull( - Connection connection, long qid, long request, PullMessageHandler handler, ValueFactory valueFactory) { - var pullMessage = new PullMessage(request, qid, valueFactory); - var pullHandler = new PullResponseHandlerImpl(handler, valueFactory); - return connection.write(pullMessage, pullHandler); - } - - @Override - protected void verifyDatabaseNameBeforeTransaction(DatabaseName databaseName) { - // Bolt V4 accepts database name - } - - @Override - public BoltProtocolVersion version() { - return VERSION; - } - - private record RouteSummaryImpl(ClusterComposition clusterComposition) implements RouteSummary {} -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v4/MessageFormatV4.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v4/MessageFormatV4.java deleted file mode 100644 index 662b736697..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v4/MessageFormatV4.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v4; - -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonMessageReader; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -public class MessageFormatV4 implements MessageFormat { - @Override - public Writer newWriter(PackOutput output, ValueFactory valueFactory) { - return new MessageWriterV4(output, valueFactory); - } - - @Override - public Reader newReader(PackInput input, ValueFactory valueFactory) { - return new CommonMessageReader(input, false, valueFactory); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v4/MessageWriterV4.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v4/MessageWriterV4.java deleted file mode 100644 index 47d8829dc5..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v4/MessageWriterV4.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v4; - -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.AbstractMessageWriter; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.BeginMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.CommitMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.DiscardMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.GoodbyeMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.HelloMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.PullMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.ResetMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.RollbackMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.RunWithMetadataMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -public class MessageWriterV4 extends AbstractMessageWriter { - public MessageWriterV4(PackOutput output, ValueFactory valueFactory) { - super(new CommonValuePacker(output, false), buildEncoders(), valueFactory); - } - - private static Map buildEncoders() { - return Map.of( - HelloMessage.SIGNATURE, new HelloMessageEncoder(), - GoodbyeMessage.SIGNATURE, new GoodbyeMessageEncoder(), - RunWithMetadataMessage.SIGNATURE, new RunWithMetadataMessageEncoder(), - DiscardMessage.SIGNATURE, new DiscardMessageEncoder(), - PullMessage.SIGNATURE, new PullMessageEncoder(), - BeginMessage.SIGNATURE, new BeginMessageEncoder(), - CommitMessage.SIGNATURE, new CommitMessageEncoder(), - RollbackMessage.SIGNATURE, new RollbackMessageEncoder(), - ResetMessage.SIGNATURE, new ResetMessageEncoder()); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v41/BoltProtocolV41.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v41/BoltProtocolV41.java deleted file mode 100644 index de0f603b75..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v41/BoltProtocolV41.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v41; - -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v4.BoltProtocolV4; - -public class BoltProtocolV41 extends BoltProtocolV4 { - public static final BoltProtocolVersion VERSION = new BoltProtocolVersion(4, 1); - public static final BoltProtocol INSTANCE = new BoltProtocolV41(); - - @Override - public BoltProtocolVersion version() { - return VERSION; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v42/BoltProtocolV42.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v42/BoltProtocolV42.java deleted file mode 100644 index 8fc19182a9..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v42/BoltProtocolV42.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v42; - -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v41.BoltProtocolV41; - -/** - * Bolt V4.2 is identical to V4.1 - */ -public class BoltProtocolV42 extends BoltProtocolV41 { - public static final BoltProtocolVersion VERSION = new BoltProtocolVersion(4, 2); - public static final BoltProtocol INSTANCE = new BoltProtocolV42(); - - @Override - public BoltProtocolVersion version() { - return VERSION; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v43/BoltProtocolV43.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v43/BoltProtocolV43.java deleted file mode 100644 index 8715ed1218..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v43/BoltProtocolV43.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v43; - -import java.time.Clock; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.ClusterComposition; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.summary.RouteSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RouteMessageResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RouteMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v42.BoltProtocolV42; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -/** - * Definition of the Bolt Protocol 4.3 - *

- * The version 4.3 use most of the 4.2 behaviours, but it extends it with new messages such as ROUTE - */ -public class BoltProtocolV43 extends BoltProtocolV42 { - public static final BoltProtocolVersion VERSION = new BoltProtocolVersion(4, 3); - public static final BoltProtocol INSTANCE = new BoltProtocolV43(); - - @Override - public MessageFormat createMessageFormat() { - return new MessageFormatV43(); - } - - @SuppressWarnings("DuplicatedCode") - @Override - public CompletionStage route( - Connection connection, - Map routingContext, - Set bookmarks, - String databaseName, - String impersonatedUser, - MessageHandler handler, - Clock clock, - LoggingProvider logging, - ValueFactory valueFactory) { - var routeMessage = new RouteMessage(routingContext, bookmarks, databaseName, impersonatedUser); - var routeFuture = new CompletableFuture>(); - routeFuture - .thenApply(map -> { - var ttl = map.get("ttl").asLong(); - var expirationTimestamp = clock.millis() + ttl * 1000; - if (ttl < 0 || ttl >= Long.MAX_VALUE / 1000L || expirationTimestamp < 0) { - expirationTimestamp = Long.MAX_VALUE; - } - - Set readers = new LinkedHashSet<>(); - Set writers = new LinkedHashSet<>(); - Set routers = new LinkedHashSet<>(); - - for (var serversMap : map.get("servers").values()) { - var role = serversMap.get("role").asString(); - for (var server : serversMap.get("addresses").values()) { - var address = new BoltServerAddress(server.asString()); - switch (role) { - case "WRITE" -> writers.add(address); - case "READ" -> readers.add(address); - case "ROUTE" -> routers.add(address); - } - } - } - var db = map.get("db"); - String name = null; - if (db != null && !db.isNull()) { - name = db.asString(); - } - - var clusterComposition = - new ClusterComposition(expirationTimestamp, readers, writers, routers, name); - return new RouteSummaryImpl(clusterComposition); - }) - .whenComplete((summary, throwable) -> { - if (throwable != null) { - handler.onError(throwable); - } else { - handler.onSummary(summary); - } - }); - var routeHandler = new RouteMessageResponseHandler(routeFuture, valueFactory); - return connection.write(routeMessage, routeHandler); - } - - @Override - public BoltProtocolVersion version() { - return VERSION; - } - - @Override - protected boolean includeDateTimeUtcPatchInHello() { - return true; - } - - private record RouteSummaryImpl(ClusterComposition clusterComposition) implements RouteSummary {} -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v43/MessageFormatV43.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v43/MessageFormatV43.java deleted file mode 100644 index ef74222f35..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v43/MessageFormatV43.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v43; - -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonMessageReader; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -/** - * Bolt message format v4.3 - */ -public class MessageFormatV43 implements MessageFormat { - private boolean dateTimeUtcEnabled; - - @Override - public Writer newWriter(PackOutput output, ValueFactory valueFactory) { - return new MessageWriterV43(output, dateTimeUtcEnabled, valueFactory); - } - - @Override - public Reader newReader(PackInput input, ValueFactory valueFactory) { - return new CommonMessageReader(input, dateTimeUtcEnabled, valueFactory); - } - - @Override - public void enableDateTimeUtc() { - dateTimeUtcEnabled = true; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v43/MessageWriterV43.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v43/MessageWriterV43.java deleted file mode 100644 index 07863eec61..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v43/MessageWriterV43.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v43; - -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.AbstractMessageWriter; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.BeginMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.CommitMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.DiscardMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.GoodbyeMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.HelloMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.PullMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.ResetMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.RollbackMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.RouteMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.RunWithMetadataMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RouteMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -/** - * Bolt message writer v4.3 - *

- * This version is able to encode all the versions existing on v4.2, but it encodes - * new messages such as ROUTE - */ -public class MessageWriterV43 extends AbstractMessageWriter { - public MessageWriterV43(PackOutput output, boolean dateTimeUtcEnabled, ValueFactory valueFactory) { - super(new CommonValuePacker(output, dateTimeUtcEnabled), buildEncoders(), valueFactory); - } - - private static Map buildEncoders() { - return Map.of( - HelloMessage.SIGNATURE, new HelloMessageEncoder(), - GoodbyeMessage.SIGNATURE, new GoodbyeMessageEncoder(), - RunWithMetadataMessage.SIGNATURE, new RunWithMetadataMessageEncoder(), - RouteMessage.SIGNATURE, new RouteMessageEncoder(), - DiscardMessage.SIGNATURE, new DiscardMessageEncoder(), - PullMessage.SIGNATURE, new PullMessageEncoder(), - BeginMessage.SIGNATURE, new BeginMessageEncoder(), - CommitMessage.SIGNATURE, new CommitMessageEncoder(), - RollbackMessage.SIGNATURE, new RollbackMessageEncoder(), - ResetMessage.SIGNATURE, new ResetMessageEncoder()); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v44/BoltProtocolV44.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v44/BoltProtocolV44.java deleted file mode 100644 index 5a122e51dc..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v44/BoltProtocolV44.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v44; - -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v43.BoltProtocolV43; - -/** - * Definition of the Bolt Protocol 4.4 - */ -public class BoltProtocolV44 extends BoltProtocolV43 { - public static final BoltProtocolVersion VERSION = new BoltProtocolVersion(4, 4); - public static final BoltProtocol INSTANCE = new BoltProtocolV44(); - - @Override - public MessageFormat createMessageFormat() { - return new MessageFormatV44(); - } - - @Override - public BoltProtocolVersion version() { - return VERSION; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v44/MessageFormatV44.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v44/MessageFormatV44.java deleted file mode 100644 index c0f7ef44f6..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v44/MessageFormatV44.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v44; - -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonMessageReader; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -/** - * Bolt message format v4.4 - */ -public class MessageFormatV44 implements MessageFormat { - private boolean dateTimeUtcEnabled; - - @Override - public MessageFormat.Writer newWriter(PackOutput output, ValueFactory valueFactory) { - return new MessageWriterV44(output, dateTimeUtcEnabled, valueFactory); - } - - @Override - public MessageFormat.Reader newReader(PackInput input, ValueFactory valueFactory) { - return new CommonMessageReader(input, dateTimeUtcEnabled, valueFactory); - } - - @Override - public void enableDateTimeUtc() { - dateTimeUtcEnabled = true; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v44/MessageWriterV44.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v44/MessageWriterV44.java deleted file mode 100644 index a4b4920714..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v44/MessageWriterV44.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v44; - -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.AbstractMessageWriter; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.BeginMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.CommitMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.DiscardMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.GoodbyeMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.HelloMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.PullMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.ResetMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.RollbackMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.RouteV44MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.RunWithMetadataMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RouteMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -/** - * Bolt message writer v4.4 - */ -public class MessageWriterV44 extends AbstractMessageWriter { - public MessageWriterV44(PackOutput output, boolean dateTimeUtcEnabled, ValueFactory valueFactory) { - super(new CommonValuePacker(output, dateTimeUtcEnabled), buildEncoders(), valueFactory); - } - - private static Map buildEncoders() { - return Map.of( - HelloMessage.SIGNATURE, new HelloMessageEncoder(), - GoodbyeMessage.SIGNATURE, new GoodbyeMessageEncoder(), - RunWithMetadataMessage.SIGNATURE, new RunWithMetadataMessageEncoder(), - RouteMessage.SIGNATURE, new RouteV44MessageEncoder(), - DiscardMessage.SIGNATURE, new DiscardMessageEncoder(), - PullMessage.SIGNATURE, new PullMessageEncoder(), - BeginMessage.SIGNATURE, new BeginMessageEncoder(), - CommitMessage.SIGNATURE, new CommitMessageEncoder(), - RollbackMessage.SIGNATURE, new RollbackMessageEncoder(), - ResetMessage.SIGNATURE, new ResetMessageEncoder()); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/BoltProtocolV5.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/BoltProtocolV5.java deleted file mode 100644 index e88de83238..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/BoltProtocolV5.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v5; - -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v44.BoltProtocolV44; - -public class BoltProtocolV5 extends BoltProtocolV44 { - public static final BoltProtocolVersion VERSION = new BoltProtocolVersion(5, 0); - public static final BoltProtocol INSTANCE = new BoltProtocolV5(); - - @Override - public MessageFormat createMessageFormat() { - return new MessageFormatV5(); - } - - @Override - public BoltProtocolVersion version() { - return VERSION; - } - - @Override - protected boolean includeDateTimeUtcPatchInHello() { - return false; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/MessageFormatV5.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/MessageFormatV5.java deleted file mode 100644 index 22ecfc1286..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/MessageFormatV5.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v5; - -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -public class MessageFormatV5 implements MessageFormat { - @Override - public Writer newWriter(PackOutput output, ValueFactory valueFactory) { - return new MessageWriterV5(output, valueFactory); - } - - @Override - public Reader newReader(PackInput input, ValueFactory valueFactory) { - return new MessageReaderV5(input, valueFactory); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/MessageReaderV5.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/MessageReaderV5.java deleted file mode 100644 index 314a4ff628..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/MessageReaderV5.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v5; - -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonMessageReader; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; - -public class MessageReaderV5 extends CommonMessageReader { - public MessageReaderV5(PackInput input, ValueFactory valueFactory) { - super(new ValueUnpackerV5(input, valueFactory), valueFactory); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/MessageWriterV5.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/MessageWriterV5.java deleted file mode 100644 index b5e5e2a80d..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/MessageWriterV5.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v5; - -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.AbstractMessageWriter; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.BeginMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.CommitMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.DiscardMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.GoodbyeMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.HelloMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.PullMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.ResetMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.RollbackMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.RouteV44MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.RunWithMetadataMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RouteMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -public class MessageWriterV5 extends AbstractMessageWriter { - public MessageWriterV5(PackOutput output, ValueFactory valueFactory) { - super(new CommonValuePacker(output, true), buildEncoders(), valueFactory); - } - - private static Map buildEncoders() { - return Map.ofEntries( - Map.entry(HelloMessage.SIGNATURE, new HelloMessageEncoder()), - Map.entry(GoodbyeMessage.SIGNATURE, new GoodbyeMessageEncoder()), - Map.entry(RunWithMetadataMessage.SIGNATURE, new RunWithMetadataMessageEncoder()), - Map.entry(RouteMessage.SIGNATURE, new RouteV44MessageEncoder()), - Map.entry(DiscardMessage.SIGNATURE, new DiscardMessageEncoder()), - Map.entry(PullMessage.SIGNATURE, new PullMessageEncoder()), - Map.entry(BeginMessage.SIGNATURE, new BeginMessageEncoder()), - Map.entry(CommitMessage.SIGNATURE, new CommitMessageEncoder()), - Map.entry(RollbackMessage.SIGNATURE, new RollbackMessageEncoder()), - Map.entry(ResetMessage.SIGNATURE, new ResetMessageEncoder())); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/ValueUnpackerV5.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/ValueUnpackerV5.java deleted file mode 100644 index dfb0034584..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/ValueUnpackerV5.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v5; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.Node; -import org.neo4j.driver.internal.bolt.api.values.Path; -import org.neo4j.driver.internal.bolt.api.values.Relationship; -import org.neo4j.driver.internal.bolt.api.values.Segment; -import org.neo4j.driver.internal.bolt.api.values.Type; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonValueUnpacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; - -public class ValueUnpackerV5 extends CommonValueUnpacker { - private static final int NODE_FIELDS = 4; - private static final int RELATIONSHIP_FIELDS = 8; - - public ValueUnpackerV5(PackInput input, ValueFactory valueFactory) { - super(input, true, valueFactory); - } - - @Override - protected int getNodeFields() { - return NODE_FIELDS; - } - - @Override - protected int getRelationshipFields() { - return RELATIONSHIP_FIELDS; - } - - @SuppressWarnings("DuplicatedCode") - @Override - protected Node unpackNode() throws IOException { - var urn = unpacker.unpackLong(); - - var numLabels = (int) unpacker.unpackListHeader(); - List labels = new ArrayList<>(numLabels); - for (var i = 0; i < numLabels; i++) { - labels.add(unpacker.unpackString()); - } - var numProps = (int) unpacker.unpackMapHeader(); - Map props = new HashMap<>(numProps); - for (var j = 0; j < numProps; j++) { - var key = unpacker.unpackString(); - props.put(key, unpack()); - } - - var elementId = unpacker.unpackString(); - - return valueFactory.node(urn, elementId, labels, props); - } - - @SuppressWarnings("DuplicatedCode") - @Override - protected Path unpackPath() throws IOException { - // List of unique nodes - var uniqNodes = new Node[(int) unpacker.unpackListHeader()]; - for (var i = 0; i < uniqNodes.length; i++) { - ensureCorrectStructSize(Type.NODE, getNodeFields(), unpacker.unpackStructHeader()); - ensureCorrectStructSignature("NODE", NODE, unpacker.unpackStructSignature()); - uniqNodes[i] = unpackNode(); - } - - // List of unique relationships, without start/end information - var uniqRels = new Relationship[(int) unpacker.unpackListHeader()]; - for (var i = 0; i < uniqRels.length; i++) { - ensureCorrectStructSize(Type.RELATIONSHIP, 4, unpacker.unpackStructHeader()); - ensureCorrectStructSignature( - "UNBOUND_RELATIONSHIP", UNBOUND_RELATIONSHIP, unpacker.unpackStructSignature()); - var id = unpacker.unpackLong(); - var relType = unpacker.unpackString(); - var props = unpackMap(); - var elementId = unpacker.unpackString(); - uniqRels[i] = valueFactory.relationship( - id, elementId, -1, String.valueOf(-1), -1, String.valueOf(-1), relType, props); - } - - // Path sequence - var length = (int) unpacker.unpackListHeader(); - - // Knowing the sequence length, we can create the arrays that will represent the nodes, rels and segments in - // their "path order" - var segments = new Segment[length / 2]; - var nodes = new Node[segments.length + 1]; - var rels = new Relationship[segments.length]; - - Node prevNode = uniqNodes[0], nextNode; // Start node is always 0, and isn't encoded in the sequence - nodes[0] = prevNode; - Relationship rel; - for (var i = 0; i < segments.length; i++) { - var relIdx = (int) unpacker.unpackLong(); - nextNode = uniqNodes[(int) unpacker.unpackLong()]; - // Negative rel index means this rel was traversed "inversed" from its direction - if (relIdx < 0) { - rel = uniqRels[(-relIdx) - 1]; // -1 because rel idx are 1-indexed - setStartAndEnd(rel, nextNode, prevNode); - } else { - rel = uniqRels[relIdx - 1]; - setStartAndEnd(rel, prevNode, nextNode); - } - - nodes[i + 1] = nextNode; - rels[i] = rel; - segments[i] = valueFactory.segment(prevNode, rel, nextNode); - prevNode = nextNode; - } - return valueFactory.path(Arrays.asList(segments), Arrays.asList(nodes), Arrays.asList(rels)); - } - - private void setStartAndEnd(Relationship rel, Node start, Node end) { - rel.setStartAndEnd(start.id(), start.elementId(), end.id(), end.elementId()); - } - - @Override - protected Relationship unpackRelationship() throws IOException { - var urn = unpacker.unpackLong(); - var startUrn = unpacker.unpackLong(); - var endUrn = unpacker.unpackLong(); - var relType = unpacker.unpackString(); - var props = unpackMap(); - var elementId = unpacker.unpackString(); - var startElementId = unpacker.unpackString(); - var endElementId = unpacker.unpackString(); - - return valueFactory.relationship( - urn, elementId, startUrn, startElementId, endUrn, endElementId, relType, props); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v51/BoltProtocolV51.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v51/BoltProtocolV51.java deleted file mode 100644 index 184cc274d9..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v51/BoltProtocolV51.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v51; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.messageDispatcher; - -import io.netty.channel.Channel; -import java.time.Clock; -import java.util.Collections; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.neo4j.driver.internal.bolt.api.BoltAgent; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.HelloV51ResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.LogoffResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.LogonResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.LogoffMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.LogonMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v5.BoltProtocolV5; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public class BoltProtocolV51 extends BoltProtocolV5 { - public static final BoltProtocolVersion VERSION = new BoltProtocolVersion(5, 1); - public static final BoltProtocol INSTANCE = new BoltProtocolV51(); - - @SuppressWarnings("DuplicatedCode") - @Override - public CompletionStage initializeChannel( - Channel channel, - String userAgent, - BoltAgent boltAgent, - Map authMap, - RoutingContext routingContext, - NotificationConfig notificationConfig, - Clock clock, - CompletableFuture latestAuthMillisFuture, - ValueFactory valueFactory) { - var exception = verifyNotificationConfigSupported(notificationConfig); - if (exception != null) { - return CompletableFuture.failedStage(exception); - } - HelloMessage message; - - if (routingContext.isServerRoutingEnabled()) { - message = new HelloMessage( - userAgent, - null, - Collections.emptyMap(), - routingContext.toMap(), - false, - notificationConfig, - useLegacyNotifications(), - valueFactory); - } else { - message = new HelloMessage( - userAgent, - null, - Collections.emptyMap(), - null, - false, - notificationConfig, - useLegacyNotifications(), - valueFactory); - } - - var helloFuture = new CompletableFuture(); - messageDispatcher(channel).enqueue(new HelloV51ResponseHandler(channel, helloFuture)); - channel.write(message, channel.voidPromise()); - - var logonFuture = new CompletableFuture(); - var logon = new LogonMessage(authMap, valueFactory); - messageDispatcher(channel) - .enqueue(new LogonResponseHandler(logonFuture, channel, clock, latestAuthMillisFuture)); - channel.writeAndFlush(logon, channel.voidPromise()); - - return helloFuture.thenCompose(ignored -> logonFuture).thenApply(ignored -> channel); - } - - @Override - public CompletionStage logoff(Connection connection, MessageHandler handler) { - var logoffMessage = LogoffMessage.INSTANCE; - var logoffFuture = new CompletableFuture(); - logoffFuture.whenComplete((ignored, throwable) -> { - if (throwable != null) { - handler.onError(throwable); - } else { - handler.onSummary(null); - } - }); - var logoffHandler = new LogoffResponseHandler(logoffFuture); - return connection.write(logoffMessage, logoffHandler); - } - - @Override - public CompletionStage logon( - Connection connection, - Map authMap, - Clock clock, - MessageHandler handler, - ValueFactory valueFactory) { - var logonMessage = new LogonMessage(authMap, valueFactory); - var logonFuture = new CompletableFuture(); - logonFuture.whenComplete((ignored, throwable) -> { - if (throwable != null) { - handler.onError(throwable); - } else { - handler.onSummary(null); - } - }); - var logonHandler = new LogonResponseHandler(logonFuture, null, clock, logonFuture); - return connection.write(logonMessage, logonHandler); - } - - @Override - public BoltProtocolVersion version() { - return VERSION; - } - - @Override - public MessageFormat createMessageFormat() { - return new MessageFormatV51(); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v51/MessageFormatV51.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v51/MessageFormatV51.java deleted file mode 100644 index bd486ecb3f..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v51/MessageFormatV51.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v51; - -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v5.MessageReaderV5; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -public class MessageFormatV51 implements MessageFormat { - @Override - public Writer newWriter(PackOutput output, ValueFactory valueFactory) { - return new MessageWriterV51(output, valueFactory); - } - - @Override - public Reader newReader(PackInput input, ValueFactory valueFactory) { - return new MessageReaderV5(input, valueFactory); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v51/MessageWriterV51.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v51/MessageWriterV51.java deleted file mode 100644 index 4b611d8e73..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v51/MessageWriterV51.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v51; - -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.AbstractMessageWriter; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.BeginMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.CommitMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.DiscardMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.GoodbyeMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.HelloMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.LogoffMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.LogonMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.PullMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.ResetMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.RollbackMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.RouteV44MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.RunWithMetadataMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.LogoffMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.LogonMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RouteMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -public class MessageWriterV51 extends AbstractMessageWriter { - public MessageWriterV51(PackOutput output, ValueFactory valueFactory) { - super(new CommonValuePacker(output, true), buildEncoders(), valueFactory); - } - - private static Map buildEncoders() { - return Map.ofEntries( - Map.entry(HelloMessage.SIGNATURE, new HelloMessageEncoder()), - Map.entry(LogonMessage.SIGNATURE, new LogonMessageEncoder()), - Map.entry(LogoffMessage.SIGNATURE, new LogoffMessageEncoder()), - Map.entry(GoodbyeMessage.SIGNATURE, new GoodbyeMessageEncoder()), - Map.entry(RunWithMetadataMessage.SIGNATURE, new RunWithMetadataMessageEncoder()), - Map.entry(RouteMessage.SIGNATURE, new RouteV44MessageEncoder()), - Map.entry(DiscardMessage.SIGNATURE, new DiscardMessageEncoder()), - Map.entry(PullMessage.SIGNATURE, new PullMessageEncoder()), - Map.entry(BeginMessage.SIGNATURE, new BeginMessageEncoder()), - Map.entry(CommitMessage.SIGNATURE, new CommitMessageEncoder()), - Map.entry(RollbackMessage.SIGNATURE, new RollbackMessageEncoder()), - Map.entry(ResetMessage.SIGNATURE, new ResetMessageEncoder())); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v52/BoltProtocolV52.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v52/BoltProtocolV52.java deleted file mode 100644 index 80ebf865a6..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v52/BoltProtocolV52.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v52; - -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.exception.BoltException; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v51.BoltProtocolV51; - -public class BoltProtocolV52 extends BoltProtocolV51 { - public static final BoltProtocolVersion VERSION = new BoltProtocolVersion(5, 2); - public static final BoltProtocol INSTANCE = new BoltProtocolV52(); - - @Override - protected BoltException verifyNotificationConfigSupported(NotificationConfig notificationConfig) { - return null; - } - - @Override - public BoltProtocolVersion version() { - return VERSION; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v53/BoltProtocolV53.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v53/BoltProtocolV53.java deleted file mode 100644 index 4704baa15f..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v53/BoltProtocolV53.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v53; - -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.messageDispatcher; - -import io.netty.channel.Channel; -import java.time.Clock; -import java.util.Collections; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.neo4j.driver.internal.bolt.api.BoltAgent; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.HelloV51ResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.LogonResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.LogonMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v52.BoltProtocolV52; - -public class BoltProtocolV53 extends BoltProtocolV52 { - public static final BoltProtocolVersion VERSION = new BoltProtocolVersion(5, 3); - public static final BoltProtocol INSTANCE = new BoltProtocolV53(); - - @SuppressWarnings("DuplicatedCode") - @Override - public CompletionStage initializeChannel( - Channel channel, - String userAgent, - BoltAgent boltAgent, - Map authMap, - RoutingContext routingContext, - NotificationConfig notificationConfig, - Clock clock, - CompletableFuture latestAuthMillisFuture, - ValueFactory valueFactory) { - var exception = verifyNotificationConfigSupported(notificationConfig); - if (exception != null) { - return CompletableFuture.failedStage(exception); - } - HelloMessage message; - - if (routingContext.isServerRoutingEnabled()) { - message = new HelloMessage( - userAgent, - boltAgent, - Collections.emptyMap(), - routingContext.toMap(), - false, - notificationConfig, - useLegacyNotifications(), - valueFactory); - } else { - message = new HelloMessage( - userAgent, - boltAgent, - Collections.emptyMap(), - null, - false, - notificationConfig, - useLegacyNotifications(), - valueFactory); - } - - var helloFuture = new CompletableFuture(); - messageDispatcher(channel).enqueue(new HelloV51ResponseHandler(channel, helloFuture)); - channel.write(message, channel.voidPromise()); - - var logonFuture = new CompletableFuture(); - var logon = new LogonMessage(authMap, valueFactory); - messageDispatcher(channel) - .enqueue(new LogonResponseHandler(logonFuture, channel, clock, latestAuthMillisFuture)); - channel.writeAndFlush(logon, channel.voidPromise()); - - return helloFuture.thenCompose(ignored -> logonFuture).thenApply(ignored -> channel); - } - - @Override - public BoltProtocolVersion version() { - return VERSION; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v54/BoltProtocolV54.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v54/BoltProtocolV54.java deleted file mode 100644 index e4735fca0e..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v54/BoltProtocolV54.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v54; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.TelemetryResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.TelemetryMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v53.BoltProtocolV53; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public class BoltProtocolV54 extends BoltProtocolV53 { - public static final BoltProtocolVersion VERSION = new BoltProtocolVersion(5, 4); - public static final BoltProtocol INSTANCE = new BoltProtocolV54(); - - @Override - public BoltProtocolVersion version() { - return VERSION; - } - - @Override - public CompletionStage telemetry(Connection connection, Integer api, MessageHandler handler) { - var telemetry = new TelemetryMessage(api); - var future = new CompletableFuture(); - future.whenComplete((ignored, throwable) -> { - if (throwable != null) { - handler.onError(throwable); - } else { - handler.onSummary(null); - } - }); - return connection.write(telemetry, new TelemetryResponseHandler(future)); - } - - @Override - public MessageFormat createMessageFormat() { - return new MessageFormatV54(); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v54/MessageFormatV54.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v54/MessageFormatV54.java deleted file mode 100644 index 435625722f..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v54/MessageFormatV54.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v54; - -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v5.MessageReaderV5; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -public class MessageFormatV54 implements MessageFormat { - @Override - public Writer newWriter(PackOutput output, ValueFactory valueFactory) { - return new MessageWriterV54(output, valueFactory); - } - - @Override - public Reader newReader(PackInput input, ValueFactory valueFactory) { - return new MessageReaderV5(input, valueFactory); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v54/MessageWriterV54.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v54/MessageWriterV54.java deleted file mode 100644 index 25a5a076bb..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v54/MessageWriterV54.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v54; - -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.AbstractMessageWriter; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.BeginMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.CommitMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.DiscardMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.GoodbyeMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.HelloMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.LogoffMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.LogonMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.PullMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.ResetMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.RollbackMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.RouteV44MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.RunWithMetadataMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.TelemetryMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.LogoffMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.LogonMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RouteMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.TelemetryMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -public class MessageWriterV54 extends AbstractMessageWriter { - public MessageWriterV54(PackOutput output, ValueFactory valueFactory) { - super(new CommonValuePacker(output, true), buildEncoders(), valueFactory); - } - - private static Map buildEncoders() { - return Map.ofEntries( - Map.entry(HelloMessage.SIGNATURE, new HelloMessageEncoder()), - Map.entry(LogonMessage.SIGNATURE, new LogonMessageEncoder()), - Map.entry(LogoffMessage.SIGNATURE, new LogoffMessageEncoder()), - Map.entry(GoodbyeMessage.SIGNATURE, new GoodbyeMessageEncoder()), - Map.entry(RunWithMetadataMessage.SIGNATURE, new RunWithMetadataMessageEncoder()), - Map.entry(RouteMessage.SIGNATURE, new RouteV44MessageEncoder()), - Map.entry(DiscardMessage.SIGNATURE, new DiscardMessageEncoder()), - Map.entry(PullMessage.SIGNATURE, new PullMessageEncoder()), - Map.entry(BeginMessage.SIGNATURE, new BeginMessageEncoder()), - Map.entry(CommitMessage.SIGNATURE, new CommitMessageEncoder()), - Map.entry(RollbackMessage.SIGNATURE, new RollbackMessageEncoder()), - Map.entry(ResetMessage.SIGNATURE, new ResetMessageEncoder()), - Map.entry(TelemetryMessage.SIGNATURE, new TelemetryMessageEncoder())); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v55/BoltProtocolV55.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v55/BoltProtocolV55.java deleted file mode 100644 index 64261ea88b..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v55/BoltProtocolV55.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v55; - -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v54.BoltProtocolV54; - -public class BoltProtocolV55 extends BoltProtocolV54 { - public static final BoltProtocolVersion VERSION = new BoltProtocolVersion(5, 5); - public static final BoltProtocol INSTANCE = new BoltProtocolV55(); - - @Override - public BoltProtocolVersion version() { - return VERSION; - } - - @Override - protected boolean useLegacyNotifications() { - return false; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v56/BoltProtocolV56.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v56/BoltProtocolV56.java deleted file mode 100644 index ed35823159..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v56/BoltProtocolV56.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v56; - -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v55.BoltProtocolV55; - -public class BoltProtocolV56 extends BoltProtocolV55 { - public static final BoltProtocolVersion VERSION = new BoltProtocolVersion(5, 6); - public static final BoltProtocol INSTANCE = new BoltProtocolV56(); - - @Override - public BoltProtocolVersion version() { - return VERSION; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v57/BoltProtocolV57.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v57/BoltProtocolV57.java deleted file mode 100644 index 2eb1a86a44..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v57/BoltProtocolV57.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v57; - -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v56.BoltProtocolV56; - -public class BoltProtocolV57 extends BoltProtocolV56 { - public static final BoltProtocolVersion VERSION = new BoltProtocolVersion(5, 7); - public static final BoltProtocol INSTANCE = new BoltProtocolV57(); - - @Override - public BoltProtocolVersion version() { - return VERSION; - } - - @Override - public MessageFormat createMessageFormat() { - return new MessageFormatV57(); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v57/MessageFormatV57.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v57/MessageFormatV57.java deleted file mode 100644 index 5de9ffac24..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v57/MessageFormatV57.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v57; - -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v54.MessageWriterV54; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -public class MessageFormatV57 implements MessageFormat { - @Override - public MessageFormat.Writer newWriter(PackOutput output, ValueFactory valueFactory) { - return new MessageWriterV54(output, valueFactory); - } - - @Override - public Reader newReader(PackInput input, ValueFactory valueFactory) { - return new MessageReaderV57(input, valueFactory); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v57/MessageReaderV57.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v57/MessageReaderV57.java deleted file mode 100644 index 10ab30bbff..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v57/MessageReaderV57.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v57; - -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.GqlError; -import org.neo4j.driver.internal.bolt.api.exception.BoltProtocolException; -import org.neo4j.driver.internal.bolt.api.values.Type; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ResponseMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v5.MessageReaderV5; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; - -public class MessageReaderV57 extends MessageReaderV5 { - public MessageReaderV57(PackInput input, ValueFactory valueFactory) { - super(input, valueFactory); - } - - @Override - protected void unpackFailureMessage(ResponseMessageHandler output) throws IOException { - var params = unpacker.unpackMap(); - var gqlError = unpackGqlError(params); - output.handleFailureMessage(gqlError); - } - - protected GqlError unpackGqlError(Map params) { - var gqlStatus = params.get("gql_status").asString(); - var statusDescription = params.get("description").asString(); - var code = params.getOrDefault("neo4j_code", valueFactory.value("N/A")).asString(); - var message = params.get("message").asString(); - Map diagnosticRecord; - var diagnosticRecordValue = params.get("diagnostic_record"); - if (diagnosticRecordValue != null && Type.MAP.equals(diagnosticRecordValue.type())) { - var containsOperation = diagnosticRecordValue.containsKey("OPERATION"); - var containsOperationCode = diagnosticRecordValue.containsKey("OPERATION_CODE"); - var containsCurrentSchema = diagnosticRecordValue.containsKey("CURRENT_SCHEMA"); - if (containsOperation && containsOperationCode && containsCurrentSchema) { - diagnosticRecord = diagnosticRecordValue.asMap(valueFactory::value); - } else { - diagnosticRecord = new HashMap<>(diagnosticRecordValue.asMap(valueFactory::value)); - if (!containsOperation) { - diagnosticRecord.put("OPERATION", valueFactory.value("")); - } - if (!containsOperationCode) { - diagnosticRecord.put("OPERATION_CODE", valueFactory.value("0")); - } - if (!containsCurrentSchema) { - diagnosticRecord.put("CURRENT_SCHEMA", valueFactory.value("/")); - } - diagnosticRecord = Collections.unmodifiableMap(diagnosticRecord); - } - } else { - diagnosticRecord = Map.ofEntries( - Map.entry("OPERATION", valueFactory.value("")), - Map.entry("OPERATION_CODE", valueFactory.value("0")), - Map.entry("CURRENT_SCHEMA", valueFactory.value("/"))); - } - - GqlError gqlError = null; - var cause = params.get("cause"); - if (cause != null) { - if (!Type.MAP.equals(cause.type())) { - throw new BoltProtocolException("Unexpected type"); - } - gqlError = unpackGqlError(cause.asMap(valueFactory::value)); - } - - return new GqlError(gqlStatus, statusDescription, code, message, diagnosticRecord, gqlError); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v58/BoltProtocolV58.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v58/BoltProtocolV58.java deleted file mode 100644 index e0c77c673a..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v58/BoltProtocolV58.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v58; - -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v57.BoltProtocolV57; - -public class BoltProtocolV58 extends BoltProtocolV57 { - public static final BoltProtocolVersion VERSION = new BoltProtocolVersion(5, 8); - public static final BoltProtocol INSTANCE = new BoltProtocolV58(); - - @Override - public BoltProtocolVersion version() { - return VERSION; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/packstream/PackInput.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/packstream/PackInput.java deleted file mode 100644 index 444945e420..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/packstream/PackInput.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.packstream; - -import java.io.IOException; - -/** - * This is what {@link PackStream} uses to ingest data, implement this on top of any data source of your choice to - * deserialize the stream with {@link PackStream}. - */ -public interface PackInput { - /** Consume one byte */ - byte readByte() throws IOException; - - /** Consume a 2-byte signed integer */ - short readShort() throws IOException; - - /** Consume a 4-byte signed integer */ - int readInt() throws IOException; - - /** Consume an 8-byte signed integer */ - long readLong() throws IOException; - - /** Consume an 8-byte IEEE 754 "double format" floating-point number */ - double readDouble() throws IOException; - - /** Consume a specified number of bytes */ - void readBytes(byte[] into, int offset, int toRead) throws IOException; - - /** Get the next byte without forwarding the internal pointer */ - byte peekByte() throws IOException; -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/packstream/PackOutput.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/packstream/PackOutput.java deleted file mode 100644 index d2acb6c3c6..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/packstream/PackOutput.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.packstream; - -import java.io.IOException; - -/** - * This is where {@link PackStream} writes its output to. - */ -public interface PackOutput { - /** Produce a single byte */ - PackOutput writeByte(byte value) throws IOException; - - /** Produce binary data */ - @SuppressWarnings("UnusedReturnValue") - PackOutput writeBytes(byte[] data) throws IOException; - - /** Produce a 4-byte signed integer */ - PackOutput writeShort(short value) throws IOException; - - /** Produce a 4-byte signed integer */ - @SuppressWarnings("UnusedReturnValue") - PackOutput writeInt(int value) throws IOException; - - /** Produce an 8-byte signed integer */ - @SuppressWarnings("UnusedReturnValue") - PackOutput writeLong(long value) throws IOException; - - /** Produce an 8-byte IEEE 754 "double format" floating-point number */ - @SuppressWarnings("UnusedReturnValue") - PackOutput writeDouble(double value) throws IOException; -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/packstream/PackStream.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/packstream/PackStream.java deleted file mode 100644 index b79c324350..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/packstream/PackStream.java +++ /dev/null @@ -1,650 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.packstream; - -import static java.lang.Integer.toHexString; -import static java.lang.String.format; -import static java.util.Collections.singletonList; - -import java.io.IOException; -import java.io.Serial; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.Map; - -/** - * PackStream is a messaging serialisation format heavily inspired by MessagePack. - * The key differences are in the type system itself which (among other things) replaces extensions with structures. - * The Packer and Unpacker implementations are also faster than their MessagePack counterparts. - *

- * Note that several marker byte values are RESERVED for future use. - * Extra markers should not be added casually and such additions must be follow a strict process involving both client and server software. - *

- * The table below shows all allocated marker byte values. - *
- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Allocated marker byte values.
MarkerBinaryTypeDescription
00..7F0xxxxxxx+TINY_INTInteger 0 to 127
80..8F1000xxxxTINY_STRING
90..9F1001xxxxTINY_LIST
A0..AF1010xxxxTINY_MAP
B0..BF1011xxxxTINY_STRUCT
C011000000NULL
C111000001FLOAT_6464-bit floating point number (double)
C211000010FALSEBoolean false
C311000011TRUEBoolean true
C4..C7110001xxRESERVED
C811001000INT_88-bit signed integer
C911001001INT_816-bit signed integer
CA11001010INT_832-bit signed integer
CB11001011INT_864-bit signed integer
CC11001100BYTES_8Byte string (fewer than 28 bytes)
CD11001101BYTES_16Byte string (fewer than 216 bytes)
CE11001110BYTES_32Byte string (fewer than 232 bytes)
CF11001111RESERVED
D011010000STRING_8UTF-8 encoded string (fewer than 28 bytes)
D111010001STRING_16UTF-8 encoded string (fewer than 216 bytes)
D211010010STRING_32UTF-8 encoded string (fewer than 232 bytes)
D311010011RESERVED
D411010100LIST_8List (fewer than 28 items)
D511010101LIST_16List (fewer than 216 items)
D611010110LIST_32List (fewer than 232 items)
D711010111RESERVED
D811011000MAP_8Map (fewer than 28 key:value pairs)
D911011001MAP_16Map (fewer than 216 key:value pairs)
DA11011010MAP_32Map (fewer than 232 key:value pairs)
DB11011011RESERVED
DC11011100STRUCT_8Structure (fewer than 28 fields)
DD11011101STRUCT_16Structure (fewer than 216 fields)
DE11011110RESERVED
DF11011111RESERVED
DF11011111RESERVED
E0..EF1110xxxxRESERVED
F0..FF1111xxxx-TINY_INTInteger -1 to -16
- * - */ -public class PackStream { - - public static final byte TINY_STRING = (byte) 0x80; - public static final byte TINY_LIST = (byte) 0x90; - public static final byte TINY_MAP = (byte) 0xA0; - public static final byte TINY_STRUCT = (byte) 0xB0; - public static final byte NULL = (byte) 0xC0; - public static final byte FLOAT_64 = (byte) 0xC1; - public static final byte FALSE = (byte) 0xC2; - public static final byte TRUE = (byte) 0xC3; - - @SuppressWarnings("unused") - public static final byte RESERVED_C4 = (byte) 0xC4; - - @SuppressWarnings("unused") - public static final byte RESERVED_C5 = (byte) 0xC5; - - @SuppressWarnings("unused") - public static final byte RESERVED_C6 = (byte) 0xC6; - - @SuppressWarnings("unused") - public static final byte RESERVED_C7 = (byte) 0xC7; - - public static final byte INT_8 = (byte) 0xC8; - public static final byte INT_16 = (byte) 0xC9; - public static final byte INT_32 = (byte) 0xCA; - public static final byte INT_64 = (byte) 0xCB; - public static final byte BYTES_8 = (byte) 0xCC; - public static final byte BYTES_16 = (byte) 0xCD; - public static final byte BYTES_32 = (byte) 0xCE; - - @SuppressWarnings("unused") - public static final byte RESERVED_CF = (byte) 0xCF; - - public static final byte STRING_8 = (byte) 0xD0; - public static final byte STRING_16 = (byte) 0xD1; - public static final byte STRING_32 = (byte) 0xD2; - - @SuppressWarnings("unused") - public static final byte RESERVED_D3 = (byte) 0xD3; - - public static final byte LIST_8 = (byte) 0xD4; - public static final byte LIST_16 = (byte) 0xD5; - public static final byte LIST_32 = (byte) 0xD6; - - @SuppressWarnings("unused") - public static final byte RESERVED_D7 = (byte) 0xD7; - - public static final byte MAP_8 = (byte) 0xD8; - public static final byte MAP_16 = (byte) 0xD9; - public static final byte MAP_32 = (byte) 0xDA; - - @SuppressWarnings("unused") - public static final byte RESERVED_DB = (byte) 0xDB; - - public static final byte STRUCT_8 = (byte) 0xDC; - public static final byte STRUCT_16 = (byte) 0xDD; - - @SuppressWarnings("unused") - public static final byte RESERVED_DE = (byte) 0xDE; - - @SuppressWarnings("unused") - public static final byte RESERVED_DF = (byte) 0xDF; - - @SuppressWarnings("unused") - public static final byte RESERVED_E0 = (byte) 0xE0; - - @SuppressWarnings("unused") - public static final byte RESERVED_E1 = (byte) 0xE1; - - @SuppressWarnings("unused") - public static final byte RESERVED_E2 = (byte) 0xE2; - - @SuppressWarnings("unused") - public static final byte RESERVED_E3 = (byte) 0xE3; - - @SuppressWarnings("unused") - public static final byte RESERVED_E4 = (byte) 0xE4; - - @SuppressWarnings("unused") - public static final byte RESERVED_E5 = (byte) 0xE5; - - @SuppressWarnings("unused") - public static final byte RESERVED_E6 = (byte) 0xE6; - - @SuppressWarnings("unused") - public static final byte RESERVED_E7 = (byte) 0xE7; - - @SuppressWarnings("unused") - public static final byte RESERVED_E8 = (byte) 0xE8; - - @SuppressWarnings("unused") - public static final byte RESERVED_E9 = (byte) 0xE9; - - @SuppressWarnings("unused") - public static final byte RESERVED_EA = (byte) 0xEA; - - @SuppressWarnings("unused") - public static final byte RESERVED_EB = (byte) 0xEB; - - @SuppressWarnings("unused") - public static final byte RESERVED_EC = (byte) 0xEC; - - @SuppressWarnings("unused") - public static final byte RESERVED_ED = (byte) 0xED; - - @SuppressWarnings("unused") - public static final byte RESERVED_EE = (byte) 0xEE; - - @SuppressWarnings("unused") - public static final byte RESERVED_EF = (byte) 0xEF; - - private static final long PLUS_2_TO_THE_31 = 2147483648L; - private static final long PLUS_2_TO_THE_16 = 65536L; - private static final long PLUS_2_TO_THE_15 = 32768L; - private static final long PLUS_2_TO_THE_7 = 128L; - private static final long MINUS_2_TO_THE_4 = -16L; - private static final long MINUS_2_TO_THE_7 = -128L; - private static final long MINUS_2_TO_THE_15 = -32768L; - private static final long MINUS_2_TO_THE_31 = -2147483648L; - - private static final String EMPTY_STRING = ""; - private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; - private static final Charset UTF_8 = StandardCharsets.UTF_8; - - private PackStream() {} - - public static class Packer { - private final PackOutput out; - - public Packer(PackOutput out) { - this.out = out; - } - - private void packRaw(byte[] data) throws IOException { - out.writeBytes(data); - } - - public void packNull() throws IOException { - out.writeByte(NULL); - } - - public void pack(boolean value) throws IOException { - out.writeByte(value ? TRUE : FALSE); - } - - public void pack(long value) throws IOException { - if (value >= MINUS_2_TO_THE_4 && value < PLUS_2_TO_THE_7) { - out.writeByte((byte) value); - } else if (value >= MINUS_2_TO_THE_7 && value < MINUS_2_TO_THE_4) { - out.writeByte(INT_8).writeByte((byte) value); - } else if (value >= MINUS_2_TO_THE_15 && value < PLUS_2_TO_THE_15) { - out.writeByte(INT_16).writeShort((short) value); - } else if (value >= MINUS_2_TO_THE_31 && value < PLUS_2_TO_THE_31) { - out.writeByte(INT_32).writeInt((int) value); - } else { - out.writeByte(INT_64).writeLong(value); - } - } - - public void pack(double value) throws IOException { - out.writeByte(FLOAT_64).writeDouble(value); - } - - public void pack(byte[] values) throws IOException { - if (values == null) { - packNull(); - } else { - packBytesHeader(values.length); - packRaw(values); - } - } - - public void pack(String value) throws IOException { - if (value == null) { - packNull(); - } else { - var utf8 = value.getBytes(UTF_8); - packStringHeader(utf8.length); - packRaw(utf8); - } - } - - private void pack(List values) throws IOException { - if (values == null) { - packNull(); - } else { - packListHeader(values.size()); - for (var value : values) { - pack(value); - } - } - } - - private void pack(Map values) throws IOException { - if (values == null) { - packNull(); - } else { - packMapHeader(values.size()); - for (var key : values.keySet()) { - pack(key); - pack(values.get(key)); - } - } - } - - public void pack(Object value) throws IOException { - if (value == null) { - packNull(); - } else if (value instanceof Boolean) { - pack((boolean) value); - } else if (value instanceof boolean[]) { - pack(singletonList(value)); - } else if (value instanceof Byte) { - pack((byte) value); - } else if (value instanceof byte[]) { - pack((byte[]) value); - } else if (value instanceof Short) { - pack((short) value); - } else if (value instanceof short[]) { - pack(singletonList(value)); - } else if (value instanceof Integer) { - pack((int) value); - } else if (value instanceof int[]) { - pack(singletonList(value)); - } else if (value instanceof Long) { - pack((long) value); - } else if (value instanceof long[]) { - pack(singletonList(value)); - } else if (value instanceof Float) { - pack((float) value); - } else if (value instanceof float[]) { - pack(singletonList(value)); - } else if (value instanceof Double) { - pack((double) value); - } else if (value instanceof double[]) { - pack(singletonList(value)); - } else if (value instanceof Character) { - pack(Character.toString((char) value)); - } else if (value instanceof char[]) { - pack(new String((char[]) value)); - } else if (value instanceof String) { - pack((String) value); - } else if (value instanceof String[]) { - pack(singletonList(value)); - } else if (value instanceof List) { - pack((List) value); - } else if (value instanceof Map) { - pack((Map) value); - } else { - throw new UnPackable(format("Cannot pack object %s", value)); - } - } - - public void packBytesHeader(int size) throws IOException { - if (size <= Byte.MAX_VALUE) { - out.writeByte(BYTES_8).writeByte((byte) size); - } else if (size < PLUS_2_TO_THE_16) { - out.writeByte(BYTES_16).writeShort((short) size); - } else { - out.writeByte(BYTES_32).writeInt(size); - } - } - - @SuppressWarnings("DuplicatedCode") - private void packStringHeader(int size) throws IOException { - if (size < 0x10) { - out.writeByte((byte) (TINY_STRING | size)); - } else if (size <= Byte.MAX_VALUE) { - out.writeByte(STRING_8).writeByte((byte) size); - } else if (size < PLUS_2_TO_THE_16) { - out.writeByte(STRING_16).writeShort((short) size); - } else { - out.writeByte(STRING_32).writeInt(size); - } - } - - @SuppressWarnings("DuplicatedCode") - public void packListHeader(int size) throws IOException { - if (size < 0x10) { - out.writeByte((byte) (TINY_LIST | size)); - } else if (size <= Byte.MAX_VALUE) { - out.writeByte(LIST_8).writeByte((byte) size); - } else if (size < PLUS_2_TO_THE_16) { - out.writeByte(LIST_16).writeShort((short) size); - } else { - out.writeByte(LIST_32).writeInt(size); - } - } - - @SuppressWarnings("DuplicatedCode") - public void packMapHeader(int size) throws IOException { - if (size < 0x10) { - out.writeByte((byte) (TINY_MAP | size)); - } else if (size <= Byte.MAX_VALUE) { - out.writeByte(MAP_8).writeByte((byte) size); - } else if (size < PLUS_2_TO_THE_16) { - out.writeByte(MAP_16).writeShort((short) size); - } else { - out.writeByte(MAP_32).writeInt(size); - } - } - - public void packStructHeader(int size, byte signature) throws IOException { - if (size < 0x10) { - out.writeByte((byte) (TINY_STRUCT | size)).writeByte(signature); - } else if (size <= Byte.MAX_VALUE) { - out.writeByte(STRUCT_8).writeByte((byte) size).writeByte(signature); - } else if (size < PLUS_2_TO_THE_16) { - out.writeByte(STRUCT_16).writeShort((short) size).writeByte(signature); - } else { - throw new Overflow("Structures cannot have more than " + (PLUS_2_TO_THE_16 - 1) + " fields"); - } - } - } - - public static class Unpacker { - private final PackInput in; - - public Unpacker(PackInput in) { - this.in = in; - } - - public long unpackStructHeader() throws IOException { - final var markerByte = in.readByte(); - final var markerHighNibble = (byte) (markerByte & 0xF0); - final var markerLowNibble = (byte) (markerByte & 0x0F); - - if (markerHighNibble == TINY_STRUCT) { - return markerLowNibble; - } - return switch (markerByte) { - case STRUCT_8 -> unpackUINT8(); - case STRUCT_16 -> unpackUINT16(); - default -> throw new Unexpected("Expected a struct, but got: " + toHexString(markerByte)); - }; - } - - public byte unpackStructSignature() throws IOException { - return in.readByte(); - } - - public long unpackListHeader() throws IOException { - final var markerByte = in.readByte(); - final var markerHighNibble = (byte) (markerByte & 0xF0); - final var markerLowNibble = (byte) (markerByte & 0x0F); - - if (markerHighNibble == TINY_LIST) { - return markerLowNibble; - } - return switch (markerByte) { - case LIST_8 -> unpackUINT8(); - case LIST_16 -> unpackUINT16(); - case LIST_32 -> unpackUINT32(); - default -> throw new Unexpected("Expected a list, but got: " + toHexString(markerByte & 0xFF)); - }; - } - - public long unpackMapHeader() throws IOException { - final var markerByte = in.readByte(); - final var markerHighNibble = (byte) (markerByte & 0xF0); - final var markerLowNibble = (byte) (markerByte & 0x0F); - - if (markerHighNibble == TINY_MAP) { - return markerLowNibble; - } - return switch (markerByte) { - case MAP_8 -> unpackUINT8(); - case MAP_16 -> unpackUINT16(); - case MAP_32 -> unpackUINT32(); - default -> throw new Unexpected("Expected a map, but got: " + toHexString(markerByte)); - }; - } - - public long unpackLong() throws IOException { - final var markerByte = in.readByte(); - if (markerByte >= MINUS_2_TO_THE_4) { - return markerByte; - } - return switch (markerByte) { - case INT_8 -> in.readByte(); - case INT_16 -> in.readShort(); - case INT_32 -> in.readInt(); - case INT_64 -> in.readLong(); - default -> throw new Unexpected("Expected an integer, but got: " + toHexString(markerByte)); - }; - } - - public double unpackDouble() throws IOException { - final var markerByte = in.readByte(); - if (markerByte == FLOAT_64) { - return in.readDouble(); - } - throw new Unexpected("Expected a double, but got: " + toHexString(markerByte)); - } - - public byte[] unpackBytes() throws IOException { - final var markerByte = in.readByte(); - switch (markerByte) { - case BYTES_8 -> { - return unpackRawBytes(unpackUINT8()); - } - case BYTES_16 -> { - return unpackRawBytes(unpackUINT16()); - } - case BYTES_32 -> { - var size = unpackUINT32(); - if (size <= Integer.MAX_VALUE) { - return unpackRawBytes((int) size); - } else { - throw new Overflow("BYTES_32 too long for Java"); - } - } - default -> throw new Unexpected("Expected bytes, but got: 0x" + toHexString(markerByte & 0xFF)); - } - } - - public String unpackString() throws IOException { - final var markerByte = in.readByte(); - if (markerByte == TINY_STRING) // Note no mask, so we compare to 0x80. - { - return EMPTY_STRING; - } - - return new String(unpackUtf8(markerByte), UTF_8); - } - - /** - * This may seem confusing. This method exists to move forward the internal pointer when encountering - * a null value. The idiomatic usage would be someone using {@link #peekNextType()} to detect a null type, - * and then this method to "skip past it". - * @return null - * @throws IOException if the unpacked value was not null - */ - @SuppressWarnings("SameReturnValue") - public Object unpackNull() throws IOException { - final var markerByte = in.readByte(); - if (markerByte != NULL) { - throw new Unexpected("Expected a null, but got: 0x" + toHexString(markerByte & 0xFF)); - } - return null; - } - - private byte[] unpackUtf8(byte markerByte) throws IOException { - final var markerHighNibble = (byte) (markerByte & 0xF0); - final var markerLowNibble = (byte) (markerByte & 0x0F); - - if (markerHighNibble == TINY_STRING) { - return unpackRawBytes(markerLowNibble); - } - switch (markerByte) { - case STRING_8 -> { - return unpackRawBytes(unpackUINT8()); - } - case STRING_16 -> { - return unpackRawBytes(unpackUINT16()); - } - case STRING_32 -> { - var size = unpackUINT32(); - if (size <= Integer.MAX_VALUE) { - return unpackRawBytes((int) size); - } else { - throw new Overflow("STRING_32 too long for Java"); - } - } - default -> throw new Unexpected("Expected a string, but got: 0x" + toHexString(markerByte & 0xFF)); - } - } - - public boolean unpackBoolean() throws IOException { - final var markerByte = in.readByte(); - return switch (markerByte) { - case TRUE -> true; - case FALSE -> false; - default -> throw new Unexpected("Expected a boolean, but got: 0x" + toHexString(markerByte & 0xFF)); - }; - } - - private int unpackUINT8() throws IOException { - return in.readByte() & 0xFF; - } - - private int unpackUINT16() throws IOException { - return in.readShort() & 0xFFFF; - } - - private long unpackUINT32() throws IOException { - return in.readInt() & 0xFFFFFFFFL; - } - - private byte[] unpackRawBytes(int size) throws IOException { - if (size == 0) { - return EMPTY_BYTE_ARRAY; - } - var heapBuffer = new byte[size]; - in.readBytes(heapBuffer, 0, heapBuffer.length); - return heapBuffer; - } - - public PackType peekNextType() throws IOException { - final var markerByte = in.peekByte(); - final var markerHighNibble = (byte) (markerByte & 0xF0); - - return switch (markerHighNibble) { - case TINY_STRING -> PackType.STRING; - case TINY_LIST -> PackType.LIST; - case TINY_MAP -> PackType.MAP; - case TINY_STRUCT -> PackType.STRUCT; - default -> switch (markerByte) { - case NULL -> PackType.NULL; - case TRUE, FALSE -> PackType.BOOLEAN; - case FLOAT_64 -> PackType.FLOAT; - case BYTES_8, BYTES_16, BYTES_32 -> PackType.BYTES; - case STRING_8, STRING_16, STRING_32 -> PackType.STRING; - case LIST_8, LIST_16, LIST_32 -> PackType.LIST; - case MAP_8, MAP_16, MAP_32 -> PackType.MAP; - case STRUCT_8, STRUCT_16 -> PackType.STRUCT; - default -> PackType.INTEGER; - }; - }; - } - } - - public static class PackStreamException extends IOException { - @Serial - private static final long serialVersionUID = -1491422133282345421L; - - protected PackStreamException(String message) { - super(message); - } - } - - public static class EndOfStream extends PackStreamException { - @Serial - private static final long serialVersionUID = 5102836237108105603L; - - public EndOfStream(String message) { - super(message); - } - } - - public static class Overflow extends PackStreamException { - @Serial - private static final long serialVersionUID = -923071934446993659L; - - public Overflow(String message) { - super(message); - } - } - - public static class Unexpected extends PackStreamException { - @Serial - private static final long serialVersionUID = 5004685868740125469L; - - public Unexpected(String message) { - super(message); - } - } - - public static class UnPackable extends PackStreamException { - @Serial - private static final long serialVersionUID = 2408740707769711365L; - - public UnPackable(String message) { - super(message); - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/packstream/PackType.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/packstream/PackType.java deleted file mode 100644 index b5ce15b808..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/packstream/PackType.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.packstream; - -public enum PackType { - NULL, - BOOLEAN, - INTEGER, - FLOAT, - BYTES, - STRING, - LIST, - MAP, - STRUCT -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/spi/Connection.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/spi/Connection.java deleted file mode 100644 index 8310cab43f..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/spi/Connection.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.spi; - -import io.netty.channel.EventLoop; -import java.time.Duration; -import java.util.Optional; -import java.util.concurrent.CompletionStage; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; - -public interface Connection { - boolean isOpen(); - - void enableAutoRead(); - - void disableAutoRead(); - - CompletionStage write(Message message, ResponseHandler handler); - - CompletionStage flush(); - - boolean isTelemetryEnabled(); - - boolean isSsrEnabled(); - - String serverAgent(); - - BoltServerAddress serverAddress(); - - BoltProtocol protocol(); - - CompletionStage forceClose(String reason); - - CompletionStage close(); - - EventLoop eventLoop(); - - Optional defaultReadTimeoutMillis(); - - void setReadTimeout(Duration duration); -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/spi/ResponseHandler.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/spi/ResponseHandler.java deleted file mode 100644 index c195137c7e..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/spi/ResponseHandler.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.spi; - -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; - -public interface ResponseHandler { - void onSuccess(Map metadata); - - void onFailure(Throwable error); - - void onRecord(Value[] fields); - - /** - * Tells whether this response handler is able to manage auto-read of the underlying connection using {@link Connection#enableAutoRead()} and - * {@link Connection#disableAutoRead()}. - *

- * Implementations can use auto-read management to apply network-level backpressure when receiving a stream of records. - * There should only be a single such handler active for a connection at one point in time. Otherwise, handlers can interfere and turn on/off auto-read - * racing with each other. {@link InboundMessageDispatcher} is responsible for tracking these handlers and disabling auto-read management to maintain just - * a single auto-read managing handler per connection. - */ - @SuppressWarnings("SameReturnValue") - default boolean canManageAutoRead() { - return false; - } - - /** - * If this response handler is able to manage auto-read of the underlying connection, then this method signals it to - * stop changing auto-read setting for the connection. - */ - default void disableAutoReadManagement() {} -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/FutureUtil.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/FutureUtil.java deleted file mode 100644 index 25e7404c26..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/FutureUtil.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.util; - -import java.util.concurrent.CompletionException; - -public class FutureUtil { - public static Throwable completionExceptionCause(Throwable error) { - if (error instanceof CompletionException) { - return error.getCause(); - } - return error; - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/LockUtil.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/LockUtil.java deleted file mode 100644 index e9ff10a015..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/LockUtil.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.util; - -import java.util.concurrent.locks.Lock; -import java.util.function.Supplier; - -public class LockUtil { - public static void executeWithLock(Lock lock, Runnable runnable) { - lock(lock); - try { - runnable.run(); - } finally { - unlock(lock); - } - } - - public static T executeWithLock(Lock lock, Supplier supplier) { - lock(lock); - try { - return supplier.get(); - } finally { - unlock(lock); - } - } - - private static void lock(Lock lock) { - lock.lock(); - } - - private static void unlock(Lock lock) { - lock.unlock(); - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/MetadataExtractor.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/MetadataExtractor.java deleted file mode 100644 index 0a9b517d0e..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/MetadataExtractor.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.util; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; -import org.neo4j.driver.internal.bolt.api.exception.BoltUntrustedServerException; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public class MetadataExtractor { - public static final int ABSENT_QUERY_ID = -1; - private final String resultAvailableAfterMetadataKey; - - public MetadataExtractor(String resultAvailableAfterMetadataKey) { - this.resultAvailableAfterMetadataKey = resultAvailableAfterMetadataKey; - } - - public List extractQueryKeys(Map metadata) { - var keysValue = metadata.get("fields"); - if (keysValue != null) { - if (!keysValue.isEmpty()) { - List keys = new ArrayList<>(keysValue.size()); - for (var value : keysValue.values()) { - keys.add(value.asString()); - } - - return keys; - } - } - return Collections.emptyList(); - } - - public long extractQueryId(Map metadata) { - var queryId = metadata.get("qid"); - if (queryId != null) { - return queryId.asLong(); - } - return ABSENT_QUERY_ID; - } - - public long extractResultAvailableAfter(Map metadata) { - var resultAvailableAfterValue = metadata.get(resultAvailableAfterMetadataKey); - if (resultAvailableAfterValue != null) { - return resultAvailableAfterValue.asLong(); - } - return -1; - } - - public static Value extractServer(Map metadata) { - var versionValue = metadata.get("server"); - if (versionValue == null || versionValue.isNull()) { - throw new BoltUntrustedServerException("Server provides no product identifier"); - } - var serverAgent = versionValue.asString(); - if (!serverAgent.startsWith("Neo4j/")) { - throw new BoltUntrustedServerException( - "Server does not identify as a genuine Neo4j instance: '" + serverAgent + "'"); - } - return versionValue; - } - - public static Set extractBoltPatches(Map metadata) { - var boltPatch = metadata.get("patch_bolt"); - if (boltPatch != null && !boltPatch.isNull()) { - return StreamSupport.stream(boltPatch.values().spliterator(), false) - .map(Value::asString) - .collect(Collectors.toSet()); - } else { - return Collections.emptySet(); - } - } -} diff --git a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/Preconditions.java b/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/Preconditions.java deleted file mode 100644 index d663b93bf3..0000000000 --- a/bolt-api-netty/src/main/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/Preconditions.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.util; - -public class Preconditions { - public static void checkArgument(Object argument, Class expectedClass) { - if (!expectedClass.isInstance(argument)) { - throw new IllegalArgumentException( - "Argument expected to be of type: " + expectedClass.getName() + " but was: " + argument); - } - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/BoltAgentUtil.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/BoltAgentUtil.java deleted file mode 100644 index 460e297854..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/BoltAgentUtil.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl; - -import org.neo4j.driver.internal.bolt.api.BoltAgent; - -public interface BoltAgentUtil { - BoltAgent VALUE = new BoltAgent("agent", null, null, null); -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/GqlErrorUtil.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/GqlErrorUtil.java deleted file mode 100644 index 9f2471cd8f..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/GqlErrorUtil.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl; - -import java.util.Map; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.GqlError; -import org.neo4j.driver.internal.bolt.api.GqlStatusError; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; - -public class GqlErrorUtil { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - - public static final Map DIAGNOSTIC_RECORD = Map.ofEntries( - Map.entry("OPERATION", valueFactory.value("")), - Map.entry("OPERATION_CODE", valueFactory.value("0")), - Map.entry("CURRENT_SCHEMA", valueFactory.value("/"))); - - public static GqlError gqlError(String code, String message) { - return new GqlError( - GqlStatusError.UNKNOWN.getStatus(), - GqlStatusError.UNKNOWN.getStatusDescription(message), - code, - message, - DIAGNOSTIC_RECORD, - null); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/NettyLoggerTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/NettyLoggerTest.java deleted file mode 100644 index 0acebff935..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/NettyLoggerTest.java +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.MockitoAnnotations.openMocks; - -import java.util.regex.Pattern; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import org.mockito.Mock; - -class NettyLoggerTest { - NettyLogger log; - - @Mock - System.Logger upstreamLog; - - @SuppressWarnings("resource") - @BeforeEach - void beforeEach() { - openMocks(this); - log = new NettyLogger("name", upstreamLog); - } - - @ParameterizedTest - @ValueSource(booleans = {true, false}) - void shouldDelegateIsTraceEnabled(boolean enabled) { - given(upstreamLog.isLoggable(System.Logger.Level.TRACE)).willReturn(enabled); - - var traceEnabled = log.isTraceEnabled(); - - assertEquals(enabled, traceEnabled); - then(upstreamLog).should().isLoggable(System.Logger.Level.TRACE); - } - - @Test - void shouldDelegateTrace() { - var message = "message"; - - log.trace(message); - - then(upstreamLog).should().log(System.Logger.Level.TRACE, message); - } - - @Test - void shouldDelegateTraceWithObject() { - var format = "message"; - var object = new Object(); - - log.trace(format, object); - - then(upstreamLog) - .should() - .log( - System.Logger.Level.TRACE, - Pattern.compile("\\{}").matcher(format).replaceAll("%s"), - object); - } - - @Test - void shouldDelegateTraceWithTwoObjects() { - var format = "message"; - var object1 = new Object(); - var object2 = new Object(); - - log.trace(format, object1, object2); - - then(upstreamLog) - .should() - .log( - System.Logger.Level.TRACE, - Pattern.compile("\\{}").matcher(format).replaceAll("%s"), - object1, - object2); - } - - @Test - void shouldDelegateTraceWithObjects() { - var format = "message"; - var objects = new Object[0]; - - log.trace(format, objects); - - then(upstreamLog) - .should() - .log( - System.Logger.Level.TRACE, - Pattern.compile("\\{}").matcher(format).replaceAll("%s"), - objects); - } - - @ParameterizedTest - @ValueSource(booleans = {true, false}) - void shouldDelegateIsDebugEnabled(boolean enabled) { - given(upstreamLog.isLoggable(System.Logger.Level.DEBUG)).willReturn(enabled); - - var traceEnabled = log.isDebugEnabled(); - - assertEquals(enabled, traceEnabled); - then(upstreamLog).should().isLoggable(System.Logger.Level.DEBUG); - } - - @Test - void shouldDelegateDebug() { - var message = "message"; - - log.debug(message); - - then(upstreamLog).should().log(System.Logger.Level.DEBUG, message); - } - - @Test - void shouldDelegateDebugWithObject() { - var format = "message"; - var object = new Object(); - - log.debug(format, object); - - then(upstreamLog) - .should() - .log( - System.Logger.Level.DEBUG, - Pattern.compile("\\{}").matcher(format).replaceAll("%s"), - object); - } - - @Test - void shouldDelegateDebugWithTwoObjects() { - var format = "message"; - var object1 = new Object(); - var object2 = new Object(); - - log.debug(format, object1, object2); - - then(upstreamLog) - .should() - .log( - System.Logger.Level.DEBUG, - Pattern.compile("\\{}").matcher(format).replaceAll("%s"), - object1, - object2); - } - - @Test - void shouldDelegateDebugWithObjects() { - var format = "message"; - var objects = new Object[0]; - - log.debug(format, objects); - - then(upstreamLog) - .should() - .log( - System.Logger.Level.DEBUG, - Pattern.compile("\\{}").matcher(format).replaceAll("%s"), - objects); - } - - @Test - void shouldDelegateDebugWithThrowable() { - var message = "message"; - var exception = new Exception(); - - log.debug(message, exception); - - then(upstreamLog).should().log(System.Logger.Level.DEBUG, "%s%n%s", message, exception); - } - - @Test - void shouldDelegateInfo() { - var message = "message"; - - log.info(message); - - then(upstreamLog).should().log(System.Logger.Level.INFO, message); - } - - @Test - void shouldDelegateInfoWithObject() { - var format = "message"; - var object = new Object(); - - log.info(format, object); - - then(upstreamLog) - .should() - .log( - System.Logger.Level.INFO, - Pattern.compile("\\{}").matcher(format).replaceAll("%s"), - object); - } - - @Test - void shouldDelegateInfoWithTwoObjects() { - var format = "message"; - var object1 = new Object(); - var object2 = new Object(); - - log.info(format, object1, object2); - - then(upstreamLog) - .should() - .log( - System.Logger.Level.INFO, - Pattern.compile("\\{}").matcher(format).replaceAll("%s"), - object1, - object2); - } - - @Test - void shouldDelegateInfoWithObjects() { - var format = "message"; - var objects = new Object[0]; - - log.info(format, objects); - - then(upstreamLog) - .should() - .log( - System.Logger.Level.INFO, - Pattern.compile("\\{}").matcher(format).replaceAll("%s"), - objects); - } - - @Test - void shouldDelegateInfoWithThrowable() { - var message = "message"; - var exception = new Exception(); - - log.info(message, exception); - - then(upstreamLog).should().log(System.Logger.Level.INFO, "%s%n%s", message, exception); - } - - @Test - void shouldDelegateWarn() { - var message = "message"; - - log.warn(message); - - then(upstreamLog).should().log(System.Logger.Level.WARNING, message); - } - - @Test - void shouldDelegateWarnWithObject() { - var format = "message"; - var object = new Object(); - - log.warn(format, object); - - then(upstreamLog) - .should() - .log( - System.Logger.Level.WARNING, - Pattern.compile("\\{}").matcher(format).replaceAll("%s"), - object); - } - - @Test - void shouldDelegateWarnWithTwoObjects() { - var format = "message"; - var object1 = new Object(); - var object2 = new Object(); - - log.warn(format, object1, object2); - - then(upstreamLog) - .should() - .log( - System.Logger.Level.WARNING, - Pattern.compile("\\{}").matcher(format).replaceAll("%s"), - object1, - object2); - } - - @Test - void shouldDelegateWarnWithObjects() { - var format = "message"; - var objects = new Object[0]; - - log.warn(format, objects); - - then(upstreamLog) - .should() - .log( - System.Logger.Level.WARNING, - Pattern.compile("\\{}").matcher(format).replaceAll("%s"), - objects); - } - - @Test - void shouldDelegateWarnWithThrowable() { - var message = "message"; - var exception = new Exception(); - - log.warn(message, exception); - - then(upstreamLog).should().log(System.Logger.Level.WARNING, "%s%n%s", message, exception); - } - - @Test - void shouldDelegateError() { - var message = "message"; - - log.error(message); - - then(upstreamLog).should().log(System.Logger.Level.ERROR, message, (Throwable) null); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/NoopLoggingProvider.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/NoopLoggingProvider.java deleted file mode 100644 index 92f1653f8e..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/NoopLoggingProvider.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl; - -import static org.mockito.Mockito.mock; - -import org.neo4j.driver.internal.bolt.api.LoggingProvider; - -public class NoopLoggingProvider implements LoggingProvider { - public static final NoopLoggingProvider INSTANCE = new NoopLoggingProvider(); - - private NoopLoggingProvider() {} - - @Override - public System.Logger getLog(Class cls) { - return mock(System.Logger.class); - } - - @Override - public System.Logger getLog(String name) { - return mock(System.Logger.class); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/BoltProtocolUtilTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/BoltProtocolUtilTest.java deleted file mode 100644 index f1eeec65d0..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/BoltProtocolUtilTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.BoltProtocolUtil.BOLT_MAGIC_PREAMBLE; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.BoltProtocolUtil.handshakeBuf; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.BoltProtocolUtil.handshakeString; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.BoltProtocolUtil.writeChunkHeader; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.BoltProtocolUtil.writeEmptyChunkHeader; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.BoltProtocolUtil.writeMessageBoundary; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.TestUtil.assertByteBufContains; - -import io.netty.buffer.Unpooled; -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3.BoltProtocolV3; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v44.BoltProtocolV44; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v58.BoltProtocolV58; - -class BoltProtocolUtilTest { - @Test - void shouldReturnHandshakeBuf() { - assertByteBufContains( - handshakeBuf(), - BOLT_MAGIC_PREAMBLE, - 0x000001FF, - (8 << 16) | BoltProtocolV58.VERSION.toInt(), - (2 << 16) | BoltProtocolV44.VERSION.toInt(), - BoltProtocolV3.VERSION.toInt()); - } - - @Test - void shouldReturnHandshakeString() { - assertEquals("[0x6060b017, 511, 526341, 132100, 3]", handshakeString()); - } - - @Test - void shouldWriteMessageBoundary() { - var buf = Unpooled.buffer(); - - buf.writeInt(1); - buf.writeInt(2); - buf.writeInt(3); - writeMessageBoundary(buf); - - assertByteBufContains(buf, 1, 2, 3, (byte) 0, (byte) 0); - } - - @Test - void shouldWriteEmptyChunkHeader() { - var buf = Unpooled.buffer(); - - writeEmptyChunkHeader(buf); - buf.writeInt(1); - buf.writeInt(2); - buf.writeInt(3); - - assertByteBufContains(buf, (byte) 0, (byte) 0, 1, 2, 3); - } - - @Test - void shouldWriteChunkHeader() { - var buf = Unpooled.buffer(); - - writeEmptyChunkHeader(buf); - buf.writeInt(1); - buf.writeInt(2); - buf.writeInt(3); - writeChunkHeader(buf, 0, 42); - - assertByteBufContains(buf, (short) 42, 1, 2, 3); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelAttributesTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelAttributesTest.java deleted file mode 100644 index d6ff98ecbe..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelAttributesTest.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.authorizationStateListener; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.connectionId; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.connectionReadTimeout; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.creationTimestamp; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.lastUsedTimestamp; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.messageDispatcher; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.protocolVersion; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.serverAddress; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.serverAgent; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setAuthorizationStateListener; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setConnectionId; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setConnectionReadTimeout; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setCreationTimestamp; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setLastUsedTimestamp; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setMessageDispatcher; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setProtocolVersion; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setServerAddress; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setServerAgent; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setTerminationReason; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.terminationReason; - -import io.netty.channel.embedded.EmbeddedChannel; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; - -class ChannelAttributesTest { - private final EmbeddedChannel channel = new EmbeddedChannel(); - - @Test - void shouldSetAndGetConnectionId() { - setConnectionId(channel, "bolt-42"); - assertEquals("bolt-42", connectionId(channel)); - } - - @Test - void shouldFailToSetConnectionIdTwice() { - setConnectionId(channel, "bolt-42"); - - assertThrows(IllegalStateException.class, () -> setConnectionId(channel, "bolt-4242")); - } - - @Test - void shouldSetAndGetProtocolVersion() { - setProtocolVersion(channel, new BoltProtocolVersion(42, 0)); - assertEquals(new BoltProtocolVersion(42, 0), protocolVersion(channel)); - } - - @Test - void shouldFailToSetProtocolVersionTwice() { - setProtocolVersion(channel, new BoltProtocolVersion(42, 0)); - - assertThrows(IllegalStateException.class, () -> setProtocolVersion(channel, new BoltProtocolVersion(43, 0))); - } - - @Test - void shouldSetAndGetServerAgent() { - var agent = "Neo4j/4.2.5"; - setServerAgent(channel, agent); - assertEquals(agent, serverAgent(channel)); - } - - @Test - void shouldFailToSetServerAgentTwice() { - var agent = "Neo4j/4.2.5"; - setServerAgent(channel, agent); - - assertThrows(IllegalStateException.class, () -> setServerAgent(channel, agent)); - } - - @Test - void shouldSetAndGetAddress() { - var address = new BoltServerAddress("local:42"); - setServerAddress(channel, address); - assertEquals(address, serverAddress(channel)); - } - - @Test - void shouldFailToSetAddressTwice() { - setServerAddress(channel, BoltServerAddress.LOCAL_DEFAULT); - - assertThrows(IllegalStateException.class, () -> setServerAddress(channel, BoltServerAddress.LOCAL_DEFAULT)); - } - - @Test - void shouldSetAndGetCreationTimestamp() { - setCreationTimestamp(channel, 42L); - assertEquals(42L, creationTimestamp(channel)); - } - - @Test - void shouldFailToSetCreationTimestampTwice() { - setCreationTimestamp(channel, 42L); - - assertThrows(IllegalStateException.class, () -> setCreationTimestamp(channel, 42L)); - } - - @Test - void shouldSetAndGetLastUsedTimestamp() { - assertNull(lastUsedTimestamp(channel)); - setLastUsedTimestamp(channel, 42L); - assertEquals(42L, lastUsedTimestamp(channel).longValue()); - } - - @Test - void shouldAllowSettingLastUsedTimestampMultipleTimes() { - setLastUsedTimestamp(channel, 42L); - setLastUsedTimestamp(channel, 4242L); - setLastUsedTimestamp(channel, 424242L); - - assertEquals(424242L, lastUsedTimestamp(channel).longValue()); - } - - @Test - void shouldSetAndGetMessageDispatcher() { - var dispatcher = mock(InboundMessageDispatcher.class); - setMessageDispatcher(channel, dispatcher); - assertEquals(dispatcher, messageDispatcher(channel)); - } - - @Test - void shouldFailToSetMessageDispatcherTwice() { - setMessageDispatcher(channel, mock(InboundMessageDispatcher.class)); - - assertThrows( - IllegalStateException.class, () -> setMessageDispatcher(channel, mock(InboundMessageDispatcher.class))); - } - - @Test - void shouldSetAndGetTerminationReason() { - var reason = "This channel has been terminated"; - setTerminationReason(channel, reason); - assertEquals(reason, terminationReason(channel)); - } - - @Test - void shouldFailToSetTerminationReasonTwice() { - setTerminationReason(channel, "Reason 1"); - - assertThrows(IllegalStateException.class, () -> setTerminationReason(channel, "Reason 2")); - } - - @Test - void shouldSetAndGetAuthorizationStateListener() { - var listener = Mockito.mock(AuthorizationStateListener.class); - setAuthorizationStateListener(channel, listener); - assertEquals(listener, authorizationStateListener(channel)); - } - - @Test - void shouldAllowOverridingAuthorizationStateListener() { - var listener = Mockito.mock(AuthorizationStateListener.class); - setAuthorizationStateListener(channel, listener); - assertEquals(listener, authorizationStateListener(channel)); - var newListener = Mockito.mock(AuthorizationStateListener.class); - setAuthorizationStateListener(channel, newListener); - assertEquals(newListener, authorizationStateListener(channel)); - } - - @Test - void shouldSetAndGetConnectionReadTimeout() { - var timeout = 15L; - setConnectionReadTimeout(channel, timeout); - assertEquals(timeout, connectionReadTimeout(channel).orElse(null)); - } - - @Test - void shouldFailToSetConnectionReadTimeoutTwice() { - var timeout = 15L; - setConnectionReadTimeout(channel, timeout); - assertThrows(IllegalStateException.class, () -> setConnectionReadTimeout(channel, timeout)); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelConnectedListenerTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelConnectedListenerTest.java deleted file mode 100644 index 48fba034e5..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelConnectedListenerTest.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.mock; -import static org.neo4j.driver.internal.bolt.api.BoltServerAddress.LOCAL_DEFAULT; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.BoltProtocolUtil.handshakeBuf; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.TestUtil.await; - -import io.netty.channel.Channel; -import io.netty.channel.ChannelPromise; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.util.concurrent.Future; -import io.netty.util.concurrent.GenericFutureListener; -import java.io.IOException; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.TimeUnit; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.exception.BoltServiceUnavailableException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; - -class ChannelConnectedListenerTest { - private final EmbeddedChannel channel = new EmbeddedChannel(); - - @AfterEach - void tearDown() { - channel.finishAndReleaseAll(); - } - - @Test - void shouldFailPromiseWhenChannelConnectionFails() { - var handshakeCompletedFuture = new CompletableFuture(); - var listener = newListener(handshakeCompletedFuture); - - var channelConnectedPromise = channel.newPromise(); - var cause = new IOException("Unable to connect!"); - channelConnectedPromise.setFailure(cause); - - listener.operationComplete(channelConnectedPromise); - - var error = assertThrows(BoltServiceUnavailableException.class, () -> await(handshakeCompletedFuture)); - assertEquals(cause, error.getCause()); - } - - @Test - void shouldWriteHandshakeWhenChannelConnected() { - var handshakeCompletedFuture = new CompletableFuture(); - var listener = newListener(handshakeCompletedFuture); - - var channelConnectedPromise = channel.newPromise(); - channelConnectedPromise.setSuccess(); - - listener.operationComplete(channelConnectedPromise); - - assertNotNull(channel.pipeline().get(HandshakeHandler.class)); - assertTrue(channel.finish()); - assertEquals(handshakeBuf(), channel.readOutbound()); - } - - @Test - void shouldCompleteHandshakePromiseExceptionallyOnWriteFailure() { - var handshakeCompletedFuture = new CompletableFuture(); - var listener = newListener(handshakeCompletedFuture); - var channelConnectedPromise = channel.newPromise(); - channelConnectedPromise.setSuccess(); - channel.close(); - - listener.operationComplete(channelConnectedPromise); - - assertTrue(handshakeCompletedFuture.isCompletedExceptionally()); - var exception = assertThrows(CompletionException.class, handshakeCompletedFuture::join); - assertInstanceOf(BoltServiceUnavailableException.class, exception.getCause()); - } - - @Test - void shouldCompleteFutureExceptionallyOnFailedPromise() { - var future = new CompletableFuture(); - var listener = newListener(future); - var throwable = mock(Throwable.class); - - listener.operationComplete(new FailedPromise(throwable)); - - assertTrue(future.isCompletedExceptionally()); - Throwable exception = assertThrows(CompletionException.class, future::join); - assertInstanceOf(BoltServiceUnavailableException.class, exception.getCause()); - exception = exception.getCause(); - assertEquals(throwable, exception.getCause()); - } - - private static ChannelConnectedListener newListener(CompletableFuture handshakeCompletedFuture) { - return new ChannelConnectedListener( - LOCAL_DEFAULT, - new ChannelPipelineBuilderImpl(), - handshakeCompletedFuture, - NoopLoggingProvider.INSTANCE, - mock(ValueFactory.class)); - } - - private record FailedPromise(Throwable failure) implements ChannelPromise { - @Override - public Channel channel() { - return null; - } - - @Override - public ChannelPromise setSuccess(Void result) { - return null; - } - - @Override - public boolean trySuccess(Void result) { - return false; - } - - @Override - public ChannelPromise setSuccess() { - return null; - } - - @Override - public boolean trySuccess() { - return false; - } - - @Override - public ChannelPromise setFailure(Throwable cause) { - return null; - } - - @Override - public boolean tryFailure(Throwable cause) { - return false; - } - - @Override - public boolean setUncancellable() { - return false; - } - - @Override - public boolean isSuccess() { - return false; - } - - @Override - public boolean isCancellable() { - return false; - } - - @Override - public Throwable cause() { - return failure; - } - - @Override - public ChannelPromise addListener(GenericFutureListener> listener) { - return null; - } - - @Override - @SafeVarargs - public final ChannelPromise addListeners(GenericFutureListener>... listeners) { - return null; - } - - @Override - public ChannelPromise removeListener(GenericFutureListener> listener) { - return null; - } - - @Override - @SafeVarargs - public final ChannelPromise removeListeners( - GenericFutureListener>... listeners) { - return null; - } - - @Override - public ChannelPromise sync() { - return null; - } - - @Override - public ChannelPromise syncUninterruptibly() { - return null; - } - - @Override - public ChannelPromise await() { - return null; - } - - @Override - public ChannelPromise awaitUninterruptibly() { - return null; - } - - @Override - public boolean await(long timeout, TimeUnit unit) { - return false; - } - - @Override - public boolean await(long timeoutMillis) { - return false; - } - - @Override - public boolean awaitUninterruptibly(long timeout, TimeUnit unit) { - return false; - } - - @Override - public boolean awaitUninterruptibly(long timeoutMillis) { - return false; - } - - @Override - public Void getNow() { - return null; - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return false; - } - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public boolean isDone() { - return false; - } - - @Override - public Void get() { - return null; - } - - @Override - public Void get(long timeout, TimeUnit unit) { - return null; - } - - @Override - public boolean isVoid() { - return false; - } - - @Override - public ChannelPromise unvoid() { - return null; - } - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelErrorHandlerTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelErrorHandlerTest.java deleted file mode 100644 index 04b7bbc58b..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelErrorHandlerTest.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setMessageDispatcher; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setTerminationReason; - -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.handler.codec.CodecException; -import java.io.IOException; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.neo4j.driver.internal.bolt.api.exception.BoltServiceUnavailableException; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.ChannelErrorHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; - -class ChannelErrorHandlerTest { - private EmbeddedChannel channel; - private InboundMessageDispatcher messageDispatcher; - - @BeforeEach - void setUp() { - channel = new EmbeddedChannel(); - messageDispatcher = mock(); - setMessageDispatcher(channel, messageDispatcher); - channel.pipeline().addLast(new ChannelErrorHandler(NoopLoggingProvider.INSTANCE)); - } - - @AfterEach - void tearDown() { - if (channel != null) { - channel.close(); - } - } - - @Test - void shouldHandleChannelInactive() { - channel.pipeline().fireChannelInactive(); - var exceptionCaptor = ArgumentCaptor.forClass(BoltServiceUnavailableException.class); - - then(messageDispatcher).should().handleChannelInactive(exceptionCaptor.capture()); - - var error = exceptionCaptor.getValue(); - assertInstanceOf(BoltServiceUnavailableException.class, error); - assertTrue(error.getMessage().startsWith("Connection to the database terminated")); - // assertFalse(channel.isOpen()); - } - - @Test - void shouldHandleChannelInactiveAfterExceptionCaught() { - var originalError = new RuntimeException("Hi!"); - var exception1 = ArgumentCaptor.forClass(RuntimeException.class); - channel.pipeline().fireExceptionCaught(originalError); - then(messageDispatcher).should().handleChannelError(exception1.capture()); - channel.pipeline().fireChannelInactive(); - var exception2 = ArgumentCaptor.forClass(RuntimeException.class); - then(messageDispatcher).should(times(2)).handleChannelError(exception2.capture()); - - var error1 = exception1.getValue(); - var error2 = exception2.getValue(); - - assertEquals(originalError, error1); - assertInstanceOf(BoltServiceUnavailableException.class, error2); - assertTrue(error2.getMessage().startsWith("Connection to the database terminated")); - // assertFalse(channel.isOpen()); - } - - @Test - void shouldHandleChannelInactiveWhenTerminationReasonSet() { - var terminationReason = "Something really bad happened"; - setTerminationReason(channel, terminationReason); - - channel.pipeline().fireChannelInactive(); - - var exceptionCaptor = ArgumentCaptor.forClass(BoltServiceUnavailableException.class); - then(messageDispatcher).should().handleChannelInactive(exceptionCaptor.capture()); - var error = exceptionCaptor.getValue(); - assertInstanceOf(BoltServiceUnavailableException.class, error); - assertTrue(error.getMessage().startsWith("Connection to the database terminated")); - assertTrue(error.getMessage().contains(terminationReason)); - // assertFalse(channel.isOpen()); - } - - @Test - void shouldHandleCodecException() { - var cause = new RuntimeException("Hi!"); - var codecException = new CodecException("Unable to encode or decode message", cause); - - channel.pipeline().fireExceptionCaught(codecException); - - var exceptionCaptor = ArgumentCaptor.forClass(RuntimeException.class); - then(messageDispatcher).should().handleChannelError(exceptionCaptor.capture()); - var error = exceptionCaptor.getValue(); - assertEquals(cause, error); - // assertFalse(channel.isOpen()); - } - - @Test - void shouldHandleCodecExceptionWithoutCause() { - var codecException = new CodecException("Unable to encode or decode message"); - - channel.pipeline().fireExceptionCaught(codecException); - - var exceptionCaptor = ArgumentCaptor.forClass(RuntimeException.class); - then(messageDispatcher).should().handleChannelError(exceptionCaptor.capture()); - var error = exceptionCaptor.getValue(); - assertEquals(codecException, error); - // assertFalse(channel.isOpen()); - } - - @Test - void shouldHandleIOException() { - var ioException = new IOException("Write or read failed"); - - channel.pipeline().fireExceptionCaught(ioException); - - var exceptionCaptor = ArgumentCaptor.forClass(RuntimeException.class); - then(messageDispatcher).should().handleChannelError(exceptionCaptor.capture()); - var error = exceptionCaptor.getValue(); - assertInstanceOf(BoltServiceUnavailableException.class, error); - assertEquals(ioException, error.getCause()); - // assertFalse(channel.isOpen()); - } - - @Test - void shouldHandleException() { - var originalError = new RuntimeException("Random failure"); - - channel.pipeline().fireExceptionCaught(originalError); - - var exceptionCaptor = ArgumentCaptor.forClass(RuntimeException.class); - then(messageDispatcher).should().handleChannelError(exceptionCaptor.capture()); - var error = exceptionCaptor.getValue(); - assertEquals(originalError, error); - // assertFalse(channel.isOpen()); - } - - @Test - void shouldHandleMultipleExceptions() { - var error1 = new RuntimeException("Failure 1"); - var error2 = new RuntimeException("Failure 2"); - - channel.pipeline().fireExceptionCaught(error1); - channel.pipeline().fireExceptionCaught(error2); - - var exceptionCaptor = ArgumentCaptor.forClass(RuntimeException.class); - then(messageDispatcher).should().handleChannelError(exceptionCaptor.capture()); - var error = exceptionCaptor.getValue(); - assertEquals(error1, error); - // assertFalse(channel.isOpen()); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelPipelineBuilderImplTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelPipelineBuilderImplTest.java deleted file mode 100644 index b1256b9bcb..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ChannelPipelineBuilderImplTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.mockito.Mockito.mock; - -import io.netty.channel.embedded.EmbeddedChannel; -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.ChannelErrorHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.ChunkDecoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.MessageDecoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.outbound.OutboundMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3.MessageFormatV3; - -class ChannelPipelineBuilderImplTest { - @Test - void shouldBuildPipeline() { - var channel = new EmbeddedChannel(); - ChannelAttributes.setMessageDispatcher( - channel, new InboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE)); - - new ChannelPipelineBuilderImpl() - .build( - new MessageFormatV3(), - channel.pipeline(), - NoopLoggingProvider.INSTANCE, - mock(ValueFactory.class)); - - var iterator = channel.pipeline().iterator(); - assertInstanceOf(ChunkDecoder.class, iterator.next().getValue()); - assertInstanceOf(MessageDecoder.class, iterator.next().getValue()); - assertInstanceOf(InboundMessageHandler.class, iterator.next().getValue()); - - assertInstanceOf(OutboundMessageHandler.class, iterator.next().getValue()); - - assertInstanceOf(ChannelErrorHandler.class, iterator.next().getValue()); - - assertFalse(iterator.hasNext()); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/EventLoopGroupFactoryTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/EventLoopGroupFactoryTest.java deleted file mode 100644 index 9070ef983d..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/EventLoopGroupFactoryTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import java.util.concurrent.ExecutionException; -import java.util.stream.StreamSupport; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; - -class EventLoopGroupFactoryTest { - private EventLoopGroup eventLoopGroup; - - @AfterEach - void tearDown() { - shutdown(eventLoopGroup); - } - - @Test - void shouldReturnCorrectChannelClass() { - assertEquals(NioSocketChannel.class, EventLoopGroupFactory.channelClass()); - } - - @Test - void shouldCreateEventLoopGroupWithSpecifiedThreadCount() { - var threadCount = 2; - eventLoopGroup = EventLoopGroupFactory.newEventLoopGroup(threadCount); - assertEquals( - threadCount, - StreamSupport.stream(eventLoopGroup.spliterator(), false).count()); - assertInstanceOf(NioEventLoopGroup.class, eventLoopGroup); - } - - @Test - void shouldAssertNotInEventLoopThread() { - eventLoopGroup = EventLoopGroupFactory.newEventLoopGroup(1); - - // current thread is not an event loop thread, assertion should not throw - EventLoopGroupFactory.assertNotInEventLoopThread(); - - // submit assertion to the event loop thread, it should fail there - var assertFuture = eventLoopGroup.submit(EventLoopGroupFactory::assertNotInEventLoopThread); - - var error = assertThrows(ExecutionException.class, () -> assertFuture.get(30, SECONDS)); - var throwable = error.getCause(); - assertTrue(throwable instanceof IllegalStateException - && throwable.getMessage() != null - && throwable.getMessage().startsWith("Blocking operation can't be executed in IO thread")); - } - - @Test - void shouldCheckIfEventLoopThread() throws Exception { - eventLoopGroup = EventLoopGroupFactory.newEventLoopGroup(1); - - var eventLoopThread = getThread(eventLoopGroup); - assertTrue(EventLoopGroupFactory.isEventLoopThread(eventLoopThread)); - - assertFalse(EventLoopGroupFactory.isEventLoopThread(Thread.currentThread())); - } - - /** - * Test verifies that our event loop group uses same kind of thread as Netty does by default. - * It's needed because default Netty setup has good performance. - */ - @Test - void shouldUseSameThreadClassAsNioEventLoopGroupDoesByDefault() throws Exception { - var nioEventLoopGroup = new NioEventLoopGroup(1); - eventLoopGroup = EventLoopGroupFactory.newEventLoopGroup(1); - try { - var defaultThread = getThread(nioEventLoopGroup); - var driverThread = getThread(eventLoopGroup); - - assertEquals(defaultThread.getClass(), driverThread.getClass().getSuperclass()); - assertEquals(defaultThread.getPriority(), driverThread.getPriority()); - } finally { - shutdown(nioEventLoopGroup); - } - } - - private static Thread getThread(EventLoopGroup eventLoopGroup) throws Exception { - return eventLoopGroup.submit(Thread::currentThread).get(10, SECONDS); - } - - private static void shutdown(EventLoopGroup group) { - if (group != null) { - try { - group.shutdownGracefully().syncUninterruptibly(); - } catch (Throwable ignore) { - } - } - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/HandshakeHandlerTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/HandshakeHandlerTest.java deleted file mode 100644 index dac229283c..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/HandshakeHandlerTest.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import static io.netty.buffer.Unpooled.copyInt; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.params.provider.Arguments.arguments; -import static org.mockito.Mockito.mock; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.BoltProtocolUtil.NO_PROTOCOL_VERSION; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setMessageDispatcher; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.TestUtil.await; - -import io.netty.channel.Channel; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.handler.codec.DecoderException; -import java.io.IOException; -import java.util.concurrent.CompletableFuture; -import java.util.stream.Stream; -import javax.net.ssl.SSLHandshakeException; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.exception.BoltClientException; -import org.neo4j.driver.internal.bolt.api.exception.BoltServiceUnavailableException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.ChunkDecoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.MessageDecoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.outbound.OutboundMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3.BoltProtocolV3; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3.MessageFormatV3; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v4.MessageFormatV4; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v42.BoltProtocolV42; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v43.BoltProtocolV43; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v43.MessageFormatV43; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v44.BoltProtocolV44; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v44.MessageFormatV44; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v5.BoltProtocolV5; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v5.MessageFormatV5; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v51.BoltProtocolV51; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v51.MessageFormatV51; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v52.BoltProtocolV52; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v53.BoltProtocolV53; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v54.BoltProtocolV54; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v54.MessageFormatV54; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v55.BoltProtocolV55; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v56.BoltProtocolV56; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v57.BoltProtocolV57; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v57.MessageFormatV57; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v58.BoltProtocolV58; - -class HandshakeHandlerTest { - private final EmbeddedChannel channel = new EmbeddedChannel(); - - @BeforeEach - void setUp() { - setMessageDispatcher(channel, new InboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE)); - } - - @AfterEach - void tearDown() { - channel.finishAndReleaseAll(); - } - - @Test - void shouldFailGivenPromiseWhenExceptionCaught() { - var handshakeCompletedFuture = new CompletableFuture(); - var handler = newHandler(handshakeCompletedFuture); - channel.pipeline().addLast(handler); - - var cause = new RuntimeException("Error!"); - channel.pipeline().fireExceptionCaught(cause); - - // promise should fail - var error = assertThrows(BoltServiceUnavailableException.class, () -> await(handshakeCompletedFuture)); - assertEquals(cause, error.getCause()); - - // channel should be closed - assertNull(await(channel.closeFuture())); - } - - @Test - void shouldFailGivenPromiseWhenServiceUnavailableExceptionCaught() { - var handshakeCompletedFuture = new CompletableFuture(); - var handler = newHandler(handshakeCompletedFuture); - channel.pipeline().addLast(handler); - - var error = new BoltServiceUnavailableException("Bad error"); - channel.pipeline().fireExceptionCaught(error); - - // promise should fail - var e = assertThrows(BoltServiceUnavailableException.class, () -> await(handshakeCompletedFuture)); - assertEquals(error, e); - - // channel should be closed - assertNull(await(channel.closeFuture())); - } - - @Test - void shouldFailGivenPromiseWhenMultipleExceptionsCaught() { - var handshakeCompletedFuture = new CompletableFuture(); - var handler = newHandler(handshakeCompletedFuture); - channel.pipeline().addLast(handler); - - var error1 = new RuntimeException("Error 1"); - var error2 = new RuntimeException("Error 2"); - channel.pipeline().fireExceptionCaught(error1); - channel.pipeline().fireExceptionCaught(error2); - - // promise should fail - var e1 = assertThrows(BoltServiceUnavailableException.class, () -> await(handshakeCompletedFuture)); - assertEquals(error1, e1.getCause()); - - // channel should be closed - assertNull(await(channel.closeFuture())); - - var e2 = assertThrows(RuntimeException.class, channel::checkException); - assertEquals(error2, e2); - } - - @Test - void shouldUnwrapDecoderException() { - var handshakeCompletedFuture = new CompletableFuture(); - var handler = newHandler(handshakeCompletedFuture); - channel.pipeline().addLast(handler); - - var cause = new IOException("Error!"); - channel.pipeline().fireExceptionCaught(new DecoderException(cause)); - - // promise should fail - var error = assertThrows(BoltServiceUnavailableException.class, () -> await(handshakeCompletedFuture)); - assertEquals(cause, error.getCause()); - - // channel should be closed - assertNull(await(channel.closeFuture())); - } - - @Test - void shouldHandleDecoderExceptionWithoutCause() { - var handshakeCompletedFuture = new CompletableFuture(); - var handler = newHandler(handshakeCompletedFuture); - channel.pipeline().addLast(handler); - - var decoderException = new DecoderException("Unable to decode a message"); - channel.pipeline().fireExceptionCaught(decoderException); - - var error = assertThrows(BoltServiceUnavailableException.class, () -> await(handshakeCompletedFuture)); - assertEquals(decoderException, error.getCause()); - - // channel should be closed - assertNull(await(channel.closeFuture())); - } - - @Test - void shouldNotTranslateSSLHandshakeException() { - var handshakeCompletedFuture = new CompletableFuture(); - var handler = newHandler(handshakeCompletedFuture); - channel.pipeline().addLast(handler); - - var error = new SSLHandshakeException("Invalid certificate"); - channel.pipeline().fireExceptionCaught(error); - - // promise should fail - var e = assertThrows(SSLHandshakeException.class, () -> await(handshakeCompletedFuture)); - assertEquals(error, e); - - // channel should be closed - assertNull(await(channel.closeFuture())); - } - - @ParameterizedTest - @MethodSource("protocolVersions") - public void testProtocolSelection( - BoltProtocolVersion protocolVersion, Class expectedMessageFormatClass) { - var handshakeCompletedFuture = new CompletableFuture(); - var pipelineBuilder = new MemorizingChannelPipelineBuilder(); - var handler = newHandler(pipelineBuilder, handshakeCompletedFuture); - channel.pipeline().addLast(handler); - - channel.pipeline().fireChannelRead(copyInt(protocolVersion.toInt())); - - // expected message format should've been used - assertInstanceOf(expectedMessageFormatClass, pipelineBuilder.usedMessageFormat); - - // handshake handler itself should be removed - assertNull(channel.pipeline().get(HandshakeHandler.class)); - - // all inbound handlers should be set - assertNotNull(channel.pipeline().get(ChunkDecoder.class)); - assertNotNull(channel.pipeline().get(MessageDecoder.class)); - assertNotNull(channel.pipeline().get(InboundMessageHandler.class)); - - // all outbound handlers should be set - assertNotNull(channel.pipeline().get(OutboundMessageHandler.class)); - - // promise should be successful - assertEquals(channel, await(handshakeCompletedFuture)); - } - - @Test - void shouldFailGivenPromiseWhenServerSuggestsNoProtocol() { - testFailure(NO_PROTOCOL_VERSION, "The server does not support any of the protocol versions"); - } - - @Test - void shouldFailGivenPromiseWhenServerSuggestsHttp() { - testFailure(new BoltProtocolVersion(80, 84), "Server responded HTTP"); - } - - @Test - void shouldFailGivenPromiseWhenServerSuggestsUnknownProtocol() { - testFailure(new BoltProtocolVersion(42, 0), "Protocol error"); - } - - @Test - void shouldFailGivenPromiseWhenChannelInactive() { - var handshakeCompletedFuture = new CompletableFuture(); - var handler = newHandler(handshakeCompletedFuture); - channel.pipeline().addLast(handler); - - channel.pipeline().fireChannelInactive(); - - // promise should fail - var error = assertThrows(BoltServiceUnavailableException.class, () -> await(handshakeCompletedFuture)); - assertEquals( - "Connection to the database terminated. Please ensure that your database is listening on the correct host and port and that you have compatible encryption settings both on Neo4j server and driver. Note that the default encryption setting has changed in Neo4j 4.0.", - error.getMessage()); - - // channel should be closed - assertNull(await(channel.closeFuture())); - } - - private void testFailure(BoltProtocolVersion serverSuggestedVersion, String expectedMessagePrefix) { - var handshakeCompletedFuture = new CompletableFuture(); - var handler = newHandler(handshakeCompletedFuture); - channel.pipeline().addLast(handler); - - channel.pipeline().fireChannelRead(copyInt(serverSuggestedVersion.toInt())); - - // handshake handler itself should be removed - assertNull(channel.pipeline().get(HandshakeHandler.class)); - - // promise should fail - var error = assertThrows(Exception.class, () -> await(handshakeCompletedFuture)); - assertInstanceOf(BoltClientException.class, error); - assertTrue(error.getMessage().startsWith(expectedMessagePrefix)); - - // channel should be closed - assertNull(await(channel.closeFuture())); - } - - private static Stream protocolVersions() { - return Stream.of( - arguments(BoltProtocolV3.VERSION, MessageFormatV3.class), - arguments(BoltProtocolV42.VERSION, MessageFormatV4.class), - arguments(BoltProtocolV43.VERSION, MessageFormatV43.class), - arguments(BoltProtocolV44.VERSION, MessageFormatV44.class), - arguments(BoltProtocolV5.VERSION, MessageFormatV5.class), - arguments(BoltProtocolV51.VERSION, MessageFormatV51.class), - arguments(BoltProtocolV52.VERSION, MessageFormatV51.class), - arguments(BoltProtocolV53.VERSION, MessageFormatV51.class), - arguments(BoltProtocolV54.VERSION, MessageFormatV54.class), - arguments(BoltProtocolV55.VERSION, MessageFormatV54.class), - arguments(BoltProtocolV56.VERSION, MessageFormatV54.class), - arguments(BoltProtocolV57.VERSION, MessageFormatV57.class), - arguments(BoltProtocolV58.VERSION, MessageFormatV57.class)); - } - - private static HandshakeHandler newHandler(CompletableFuture handshakeCompletedFuture) { - return newHandler(new ChannelPipelineBuilderImpl(), handshakeCompletedFuture); - } - - private static HandshakeHandler newHandler( - ChannelPipelineBuilder pipelineBuilder, CompletableFuture handshakeCompletedPromise) { - return new HandshakeHandler( - pipelineBuilder, handshakeCompletedPromise, NoopLoggingProvider.INSTANCE, mock(ValueFactory.class)); - } - - private static class MemorizingChannelPipelineBuilder extends ChannelPipelineBuilderImpl { - MessageFormat usedMessageFormat; - - @Override - public void build( - MessageFormat messageFormat, - ChannelPipeline pipeline, - LoggingProvider logging, - ValueFactory valueFactory) { - usedMessageFormat = messageFormat; - super.build(messageFormat, pipeline, logging, valueFactory); - } - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ManifestHandlerV1Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ManifestHandlerV1Test.java deleted file mode 100644 index e65a370f75..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/ManifestHandlerV1Test.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.mockito.MockitoAnnotations.openMocks; - -import io.netty.buffer.Unpooled; -import io.netty.channel.embedded.EmbeddedChannel; -import java.util.stream.Stream; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.Mock; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.exception.BoltClientException; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; - -class ManifestHandlerV1Test { - ManifestHandlerV1 handler; - - EmbeddedChannel embeddedChannel = new EmbeddedChannel(); - - @Mock - LoggingProvider loggingProvider; - - System.Logger logger; - - @BeforeEach - void beforeEach() { - openMocks(this); - given(loggingProvider.getLog(any(Class.class))).willReturn(mock(System.Logger.class)); - handler = new ManifestHandlerV1(embeddedChannel, loggingProvider); - } - - @Test - void shouldThrowOnRangeOverflow() { - for (var val : new byte[] {-1, -1, -1, -1, -1, -1, -1, -1, -1}) { - handler.decode(Unpooled.copiedBuffer(new byte[] {val})); - } - - assertThrows(BoltClientException.class, () -> handler.decode(Unpooled.copiedBuffer(new byte[] {-1}))); - } - - @Test - void shouldThrowOnRangeLargerThanMaxInteger() { - for (var val : new byte[] {-1, -1, -1, -1}) { - handler.decode(Unpooled.copiedBuffer(new byte[] {val})); - } - - assertThrows(BoltClientException.class, () -> handler.decode(Unpooled.copiedBuffer(new byte[] {0b00001111}))); - } - - @ParameterizedTest - @MethodSource("shouldSelectProtocolArgs") - void shouldSelectProtocol(BoltProtocol protocol) { - handler.decode(Unpooled.copiedBuffer(new byte[] {1})); - handler.decode(Unpooled.copyInt(protocol.version().toInt())); - assertEquals(protocol, handler.complete()); - } - - static Stream shouldSelectProtocolArgs() { - return BoltProtocolUtil.versionToProtocol.values().stream().map(Arguments::of); - } - - @Test - void shouldThrowOnUnsupportedVersion() { - handler.decode(Unpooled.copiedBuffer(new byte[] {1})); - handler.decode(Unpooled.copyInt(0x00000104)); - - assertThrows(BoltClientException.class, () -> handler.complete()); - var outboundMessages = embeddedChannel.outboundMessages(); - assertEquals(2, outboundMessages.size()); - assertEquals(Unpooled.copyInt(0), outboundMessages.poll()); - assertEquals(Unpooled.copiedBuffer(new byte[] {0}), outboundMessages.poll()); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/NettyChannelInitializerTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/NettyChannelInitializerTest.java deleted file mode 100644 index 05a44f92e5..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/NettyChannelInitializerTest.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.api.BoltServerAddress.LOCAL_DEFAULT; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.creationTimestamp; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.messageDispatcher; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.serverAddress; - -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.handler.ssl.SslHandler; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.time.Clock; -import javax.net.ssl.KeyManager; -import javax.net.ssl.SNIHostName; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; -import org.neo4j.driver.internal.bolt.api.SecurityPlans; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; - -class NettyChannelInitializerTest { - private final EmbeddedChannel channel = new EmbeddedChannel(); - - @AfterEach - void tearDown() { - channel.finishAndReleaseAll(); - } - - @Test - void shouldAddSslHandlerWhenRequiresEncryption() { - var security = trustAllCertificates(false); - var initializer = newInitializer(security); - - initializer.initChannel(channel); - - assertNotNull(channel.pipeline().get(SslHandler.class)); - } - - @Test - void shouldNotAddSslHandlerWhenDoesNotRequireEncryption() { - var security = SecurityPlans.unencrypted(); - var initializer = newInitializer(security); - - initializer.initChannel(channel); - - assertNull(channel.pipeline().get(SslHandler.class)); - } - - @Test - void shouldAddSslHandlerWithHandshakeTimeout() { - var timeoutMillis = 424242; - var security = trustAllCertificates(false); - var initializer = newInitializer(security, timeoutMillis); - - initializer.initChannel(channel); - - var sslHandler = channel.pipeline().get(SslHandler.class); - assertNotNull(sslHandler); - assertEquals(timeoutMillis, sslHandler.getHandshakeTimeoutMillis()); - } - - @Test - void shouldUpdateChannelAttributes() { - var clock = mock(Clock.class); - when(clock.millis()).thenReturn(42L); - var security = SecurityPlans.unencrypted(); - var initializer = newInitializer(security, Integer.MAX_VALUE, clock); - - initializer.initChannel(channel); - - assertEquals(LOCAL_DEFAULT, serverAddress(channel)); - assertEquals(42L, creationTimestamp(channel)); - assertNotNull(messageDispatcher(channel)); - } - - @Test - void shouldIncludeSniHostName() { - var address = new BoltServerAddress("database.neo4j.com", 8989); - var initializer = new NettyChannelInitializer( - address, trustAllCertificates(false), 10000, Clock.systemUTC(), NoopLoggingProvider.INSTANCE); - - initializer.initChannel(channel); - - var sslHandler = channel.pipeline().get(SslHandler.class); - var sslEngine = sslHandler.engine(); - var sslParameters = sslEngine.getSSLParameters(); - var sniServerNames = sslParameters.getServerNames(); - assertEquals(1, sniServerNames.size()); - assertInstanceOf(SNIHostName.class, sniServerNames.get(0)); - assertEquals(address.host(), ((SNIHostName) sniServerNames.get(0)).getAsciiName()); - } - - @Test - void shouldEnableHostnameVerificationWhenConfigured() { - testHostnameVerificationSetting(true, "HTTPS"); - } - - @Test - void shouldNotEnableHostnameVerificationWhenNotConfigured() { - testHostnameVerificationSetting(false, null); - } - - private void testHostnameVerificationSetting(boolean enabled, String expectedValue) { - var initializer = newInitializer(trustAllCertificates(enabled)); - - initializer.initChannel(channel); - - var sslHandler = channel.pipeline().get(SslHandler.class); - var sslEngine = sslHandler.engine(); - var sslParameters = sslEngine.getSSLParameters(); - assertEquals(expectedValue, sslParameters.getEndpointIdentificationAlgorithm()); - } - - private static NettyChannelInitializer newInitializer(SecurityPlan securityPlan) { - return newInitializer(securityPlan, Integer.MAX_VALUE); - } - - private static NettyChannelInitializer newInitializer(SecurityPlan securityPlan, int connectTimeoutMillis) { - return newInitializer(securityPlan, connectTimeoutMillis, Clock.systemUTC()); - } - - private static NettyChannelInitializer newInitializer( - SecurityPlan securityPlan, int connectTimeoutMillis, Clock clock) { - return new NettyChannelInitializer( - LOCAL_DEFAULT, securityPlan, connectTimeoutMillis, clock, NoopLoggingProvider.INSTANCE); - } - - private static SecurityPlan trustAllCertificates(boolean enabled) { - return new SecurityPlan() { - @Override - public boolean requiresEncryption() { - return true; - } - - @Override - public boolean requiresClientAuth() { - return false; - } - - @Override - public SSLContext sslContext() { - SSLContext sslContext; - try { - sslContext = SSLContext.getInstance("TLS"); - sslContext.init(new KeyManager[0], new TrustManager[] {new TrustAllTrustManager()}, null); - } catch (NoSuchAlgorithmException | KeyManagementException e) { - throw new RuntimeException(e); - } - return sslContext; - } - - @Override - public boolean requiresHostnameVerification() { - return enabled; - } - - private static class TrustAllTrustManager implements X509TrustManager { - public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { - throw new CertificateException("All client connections to this client are forbidden."); - } - - public void checkServerTrusted(X509Certificate[] chain, String authType) { - // all fine, pass through - } - - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } - } - }; - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/VarLongBuilderTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/VarLongBuilderTest.java deleted file mode 100644 index 7779c93270..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/connection/VarLongBuilderTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.params.provider.Arguments.arguments; - -import java.util.stream.Stream; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -class VarLongBuilderTest { - VarLongBuilder builder; - - @BeforeEach - void beforeEach() { - builder = new VarLongBuilder(); - } - - @ParameterizedTest - @MethodSource("shouldBuildArgs") - void shouldBuild(byte[] segments, long value) { - for (var segment : segments) { - builder.add(segment); - } - - assertEquals(value, builder.build()); - } - - @Test - void shouldThrowOnOverflow() { - var segments = new byte[] {127, 127, 127, 127, 127, 127, 127, 127, 127}; - for (var segment : segments) { - builder.add(segment); - } - - assertThrows(IllegalStateException.class, () -> builder.add(0)); - } - - private static Stream shouldBuildArgs() { - return Stream.of( - arguments(new byte[] {0}, 0L), - arguments(new byte[] {127}, 127L), - arguments(new byte[] {(byte) 0b00010110, 1}, 150L), - arguments(new byte[] {127, 127, 127, 127, (byte) 0b00000111}, Integer.MAX_VALUE), - arguments(new byte[] {127, 127, 127, 127, 127, 127, 127, 127, 127}, Long.MAX_VALUE)); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ByteBufInputTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ByteBufInputTest.java deleted file mode 100644 index b4252e25ea..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ByteBufInputTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import io.netty.buffer.ByteBuf; -import org.junit.jupiter.api.Test; - -class ByteBufInputTest { - @Test - void shouldThrowWhenStartedWithNullBuf() { - var input = new ByteBufInput(); - - assertThrows(NullPointerException.class, () -> input.start(null)); - } - - @Test - void shouldThrowWhenStartedTwice() { - var input = new ByteBufInput(); - input.start(mock(ByteBuf.class)); - - assertThrows(IllegalStateException.class, () -> input.start(mock(ByteBuf.class))); - } - - @Test - void shouldDelegateReadByte() { - var input = new ByteBufInput(); - var buf = mock(ByteBuf.class); - when(buf.readByte()).thenReturn((byte) 42); - input.start(buf); - - assertEquals((byte) 42, input.readByte()); - } - - @Test - void shouldDelegateReadShort() { - var input = new ByteBufInput(); - var buf = mock(ByteBuf.class); - when(buf.readShort()).thenReturn((short) -42); - input.start(buf); - - assertEquals((short) -42, input.readShort()); - } - - @Test - void shouldDelegateReadInt() { - var input = new ByteBufInput(); - var buf = mock(ByteBuf.class); - when(buf.readInt()).thenReturn(15); - input.start(buf); - - assertEquals(15, input.readInt()); - } - - @Test - void shouldDelegateReadLong() { - var input = new ByteBufInput(); - var buf = mock(ByteBuf.class); - when(buf.readLong()).thenReturn(4242L); - input.start(buf); - - assertEquals(4242L, input.readLong()); - } - - @Test - void shouldDelegateReadDouble() { - var input = new ByteBufInput(); - var buf = mock(ByteBuf.class); - when(buf.readDouble()).thenReturn(42.42D); - input.start(buf); - - assertEquals(42.42D, input.readDouble(), 0.00001); - } - - @Test - void shouldDelegateReadBytes() { - var input = new ByteBufInput(); - var buf = mock(ByteBuf.class); - input.start(buf); - - input.readBytes(new byte[10], 3, 5); - - verify(buf).readBytes(new byte[10], 3, 5); - } - - @Test - void shouldDelegatePeekByte() { - var input = new ByteBufInput(); - var buf = mock(ByteBuf.class); - when(buf.getByte(anyInt())).thenReturn((byte) 42); - input.start(buf); - - assertEquals((byte) 42, input.peekByte()); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ChunkDecoderTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ChunkDecoderTest.java deleted file mode 100644 index cf017ca66a..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ChunkDecoderTest.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound; - -import static io.netty.buffer.ByteBufUtil.hexDump; -import static io.netty.buffer.Unpooled.buffer; -import static io.netty.buffer.Unpooled.copyShort; -import static io.netty.buffer.Unpooled.wrappedBuffer; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.TestUtil.assertByteBufEquals; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.embedded.EmbeddedChannel; -import java.util.ResourceBundle; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; - -class ChunkDecoderTest { - private ByteBuf buffer; - private EmbeddedChannel channel = new EmbeddedChannel(newChunkDecoder()); - - @AfterEach - void tearDown() { - if (buffer != null) { - buffer.release(buffer.refCnt()); - } - if (channel != null) { - channel.finishAndReleaseAll(); - } - } - - @Test - void shouldDecodeFullChunk() { - // whole chunk with header and body arrives at once - var input = buffer(); - input.writeShort(7); - input.writeByte(1); - input.writeByte(11); - input.writeByte(2); - input.writeByte(22); - input.writeByte(3); - input.writeByte(33); - input.writeByte(4); - - // after buffer is written there should be something to read on the other side - assertTrue(channel.writeInbound(input)); - assertTrue(channel.finish()); - - // there should only be a single chunk available for reading - assertEquals(1, channel.inboundMessages().size()); - // it should have no size header and expected body - assertByteBufEquals(input.slice(2, 7), channel.readInbound()); - } - - @Test - void shouldDecodeSplitChunk() { - // first part of the chunk contains size header and some bytes - var input1 = buffer(); - input1.writeShort(9); - input1.writeByte(1); - input1.writeByte(11); - input1.writeByte(2); - // nothing should be available for reading - assertFalse(channel.writeInbound(input1)); - - // second part contains just a single byte - var input2 = buffer(); - input2.writeByte(22); - // nothing should be available for reading - assertFalse(channel.writeInbound(input2)); - - // third part contains couple more bytes - var input3 = buffer(); - input3.writeByte(3); - input3.writeByte(33); - input3.writeByte(4); - // nothing should be available for reading - assertFalse(channel.writeInbound(input3)); - - // fourth part contains couple more bytes, and the chunk is now complete - var input4 = buffer(); - input4.writeByte(44); - input4.writeByte(5); - // there should be something to read now - assertTrue(channel.writeInbound(input4)); - - assertTrue(channel.finish()); - - // there should only be a single chunk available for reading - assertEquals(1, channel.inboundMessages().size()); - // it should have no size header and expected body - assertByteBufEquals(wrappedBuffer(new byte[] {1, 11, 2, 22, 3, 33, 4, 44, 5}), channel.readInbound()); - } - - @Test - void shouldDecodeEmptyChunk() { - // chunk contains just the size header which is zero - var input = copyShort(0); - assertTrue(channel.writeInbound(input)); - assertTrue(channel.finish()); - - // there should only be a single chunk available for reading - assertEquals(1, channel.inboundMessages().size()); - // it should have no size header and empty body - assertByteBufEquals(wrappedBuffer(new byte[0]), channel.readInbound()); - } - - @Test - void shouldLogEmptyChunkOnTraceLevel() { - var logger = newTraceLogger(); - channel = new EmbeddedChannel(new ChunkDecoder(newLogging(logger))); - - buffer = copyShort(0); - assertTrue(channel.writeInbound(buffer.copy())); // copy buffer so we can verify against it later - assertTrue(channel.finish()); - - var messageCaptor = ArgumentCaptor.forClass(String.class); - verify(logger) - .log(eq(System.Logger.Level.TRACE), eq((ResourceBundle) null), anyString(), messageCaptor.capture()); - - // pretty hex dump should be logged - assertEquals(hexDump(buffer), messageCaptor.getValue()); - // single empty chunk should be available for reading - assertEquals(1, channel.inboundMessages().size()); - assertByteBufEquals(wrappedBuffer(new byte[0]), channel.readInbound()); - } - - @Test - void shouldLogNonEmptyChunkOnTraceLevel() { - var logger = newTraceLogger(); - channel = new EmbeddedChannel(new ChunkDecoder(newLogging(logger))); - - var bytes = "Hello".getBytes(); - buffer = buffer(); - buffer.writeShort(bytes.length); - buffer.writeBytes(bytes); - - assertTrue(channel.writeInbound(buffer.copy())); // copy buffer so we can verify against it later - assertTrue(channel.finish()); - - var messageCaptor = ArgumentCaptor.forClass(String.class); - verify(logger) - .log(eq(System.Logger.Level.TRACE), eq((ResourceBundle) null), anyString(), messageCaptor.capture()); - - // pretty hex dump should be logged - assertEquals(hexDump(buffer), messageCaptor.getValue()); - // single chunk should be available for reading - assertEquals(1, channel.inboundMessages().size()); - assertByteBufEquals(wrappedBuffer(bytes), channel.readInbound()); - } - - @Test - public void shouldDecodeMaxSizeChunk() { - var message = new byte[0xFFFF]; - - var input = buffer(); - input.writeShort(message.length); // chunk header - input.writeBytes(message); // chunk body - - assertTrue(channel.writeInbound(input)); - assertTrue(channel.finish()); - - assertEquals(1, channel.inboundMessages().size()); - assertByteBufEquals(wrappedBuffer(message), channel.readInbound()); - } - - private static ChunkDecoder newChunkDecoder() { - return new ChunkDecoder(NoopLoggingProvider.INSTANCE); - } - - private static System.Logger newTraceLogger() { - var logger = mock(System.Logger.class); - when(logger.isLoggable(System.Logger.Level.TRACE)).thenReturn(true); - return logger; - } - - private static LoggingProvider newLogging(System.Logger logger) { - var logging = mock(LoggingProvider.class); - when(logging.getLog(any(Class.class))).thenReturn(logger); - return logging; - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ConnectTimeoutHandlerTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ConnectTimeoutHandlerTest.java deleted file mode 100644 index acd3efa842..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ConnectTimeoutHandlerTest.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import io.netty.channel.embedded.EmbeddedChannel; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.exception.BoltServiceUnavailableException; - -class ConnectTimeoutHandlerTest { - private final EmbeddedChannel channel = new EmbeddedChannel(); - - @AfterEach - void tearDown() { - channel.finishAndReleaseAll(); - } - - @Test - void shouldFireExceptionOnTimeout() throws Exception { - var timeoutMillis = 100; - channel.pipeline().addLast(new ConnectTimeoutHandler(timeoutMillis)); - - // sleep for more than the timeout value - Thread.sleep(timeoutMillis * 4); - channel.runPendingTasks(); - - var error = assertThrows(BoltServiceUnavailableException.class, channel::checkException); - assertEquals(error.getMessage(), "Unable to establish connection in " + timeoutMillis + "ms"); - } - - @Test - void shouldNotFireExceptionMultipleTimes() throws Exception { - var timeoutMillis = 70; - channel.pipeline().addLast(new ConnectTimeoutHandler(timeoutMillis)); - - // sleep for more than the timeout value - Thread.sleep(timeoutMillis * 4); - channel.runPendingTasks(); - - var error = assertThrows(BoltServiceUnavailableException.class, channel::checkException); - assertEquals(error.getMessage(), "Unable to establish connection in " + timeoutMillis + "ms"); - - // sleep even more - Thread.sleep(timeoutMillis * 4); - channel.runPendingTasks(); - - // no more exceptions should occur - channel.checkException(); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ConnectionReadTimeoutHandlerTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ConnectionReadTimeoutHandlerTest.java deleted file mode 100644 index 6bea76e11a..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/ConnectionReadTimeoutHandlerTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound; - -import static org.mockito.BDDMockito.any; -import static org.mockito.BDDMockito.then; -import static org.mockito.BDDMockito.times; -import static org.mockito.Mockito.mock; - -import io.netty.channel.ChannelHandlerContext; -import java.util.concurrent.TimeUnit; -import java.util.stream.IntStream; -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.exception.BoltConnectionReadTimeoutException; - -public class ConnectionReadTimeoutHandlerTest { - final ConnectionReadTimeoutHandler handler = new ConnectionReadTimeoutHandler(15L, TimeUnit.SECONDS); - final ChannelHandlerContext context = mock(ChannelHandlerContext.class); - - @Test - void shouldFireConnectionReadTimeoutExceptionAndCloseChannelOnReadTimeOutOnce() { - // WHEN - IntStream.range(0, 10).forEach(i -> handler.readTimedOut(context)); - - // THEN - then(context).should(times(1)).fireExceptionCaught(any(BoltConnectionReadTimeoutException.class)); - then(context).should(times(1)).close(); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/InboundMessageDispatcherTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/InboundMessageDispatcherTest.java deleted file mode 100644 index ff0b19646d..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/InboundMessageDispatcherTest.java +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound; - -import static java.util.Collections.emptyMap; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.contains; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import io.netty.channel.Channel; -import io.netty.channel.ChannelConfig; -import io.netty.channel.DefaultChannelId; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.util.Attribute; -import java.util.HashMap; -import java.util.Map; -import java.util.ResourceBundle; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import org.mockito.ArgumentCaptor; -import org.mockito.ArgumentMatchers; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.exception.BoltFailureException; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.GqlErrorUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.logging.ChannelActivityLogger; -import org.neo4j.driver.internal.bolt.basicimpl.impl.logging.ChannelErrorLogger; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.FailureMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.IgnoredMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.RecordMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.SuccessMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.ResponseHandler; - -class InboundMessageDispatcherTest { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private static final String FAILURE_CODE = "Neo.ClientError.Security.Unauthorized"; - private static final String FAILURE_MESSAGE = "Error Message"; - - @Test - void shouldFailWhenCreatedWithNullChannel() { - assertThrows( - NullPointerException.class, () -> new InboundMessageDispatcher(null, NoopLoggingProvider.INSTANCE)); - } - - @Test - void shouldFailWhenCreatedWithNullLogging() { - assertThrows(NullPointerException.class, () -> new InboundMessageDispatcher(newChannelMock(), null)); - } - - @Test - void shouldDequeHandlerOnSuccess() { - var dispatcher = newDispatcher(); - - var handler = mock(ResponseHandler.class); - dispatcher.enqueue(handler); - assertEquals(1, dispatcher.queuedHandlersCount()); - - Map metadata = new HashMap<>(); - metadata.put("key1", valueFactory.value(1)); - metadata.put("key2", valueFactory.value("2")); - dispatcher.handleSuccessMessage(metadata); - - assertEquals(0, dispatcher.queuedHandlersCount()); - verify(handler).onSuccess(metadata); - } - - @Test - void shouldDequeHandlerOnFailure() { - var channel = new EmbeddedChannel(); - var dispatcher = newDispatcher(channel); - - var handler = mock(ResponseHandler.class); - dispatcher.enqueue(handler); - assertEquals(1, dispatcher.queuedHandlersCount()); - - dispatcher.handleFailureMessage(GqlErrorUtil.gqlError(FAILURE_CODE, FAILURE_MESSAGE)); - - assertEquals(0, dispatcher.queuedHandlersCount()); - verifyFailure(handler); - } - - @Test - void shouldPeekHandlerOnRecord() { - var dispatcher = newDispatcher(); - - var handler = mock(ResponseHandler.class); - dispatcher.enqueue(handler); - assertEquals(1, dispatcher.queuedHandlersCount()); - - var fields1 = new Value[] {valueFactory.value(1)}; - var fields2 = new Value[] {valueFactory.value(2)}; - var fields3 = new Value[] {valueFactory.value(3)}; - - dispatcher.handleRecordMessage(fields1); - dispatcher.handleRecordMessage(fields2); - dispatcher.handleRecordMessage(fields3); - - verify(handler).onRecord(fields1); - verify(handler).onRecord(fields2); - verify(handler).onRecord(fields3); - assertEquals(1, dispatcher.queuedHandlersCount()); - } - - @Test - void shouldFailAllHandlersOnChannelError() { - var dispatcher = newDispatcher(); - - var handler1 = mock(ResponseHandler.class); - var handler2 = mock(ResponseHandler.class); - var handler3 = mock(ResponseHandler.class); - - dispatcher.enqueue(handler1); - dispatcher.enqueue(handler2); - dispatcher.enqueue(handler3); - - var fatalError = new RuntimeException("Fatal!"); - dispatcher.handleChannelError(fatalError); - - var inOrder = inOrder(handler1, handler2, handler3); - inOrder.verify(handler1).onFailure(fatalError); - inOrder.verify(handler2).onFailure(fatalError); - inOrder.verify(handler3).onFailure(fatalError); - } - - @Test - void shouldFailNewHandlerAfterChannelError() { - var dispatcher = newDispatcher(); - - dispatcher.handleChannelError(new RuntimeException("Fatal!")); - - var handler = mock(ResponseHandler.class); - dispatcher.enqueue(handler); - - verify(handler).onFailure(ArgumentMatchers.any(IllegalStateException.class)); - } - - @Test - void shouldDequeHandlerOnIgnored() { - var dispatcher = newDispatcher(); - var handler = mock(ResponseHandler.class); - - dispatcher.enqueue(handler); - dispatcher.handleIgnoredMessage(); - - assertEquals(0, dispatcher.queuedHandlersCount()); - } - - @Test - void shouldThrowWhenNoHandlerToHandleRecordMessage() { - var dispatcher = newDispatcher(); - - assertThrows( - IllegalStateException.class, - () -> dispatcher.handleRecordMessage(new Value[] {valueFactory.value(1), valueFactory.value(2)})); - } - - @Test - void shouldKeepSingleAutoReadManagingHandler() { - var dispatcher = newDispatcher(); - - var handler1 = newAutoReadManagingResponseHandler(); - var handler2 = newAutoReadManagingResponseHandler(); - var handler3 = newAutoReadManagingResponseHandler(); - - dispatcher.enqueue(handler1); - dispatcher.enqueue(handler2); - dispatcher.enqueue(handler3); - - var inOrder = inOrder(handler1, handler2, handler3); - inOrder.verify(handler1).disableAutoReadManagement(); - inOrder.verify(handler2).disableAutoReadManagement(); - inOrder.verify(handler3, never()).disableAutoReadManagement(); - } - - @Test - void shouldKeepTrackOfAutoReadManagingHandler() { - var dispatcher = newDispatcher(); - - var handler1 = newAutoReadManagingResponseHandler(); - var handler2 = newAutoReadManagingResponseHandler(); - - assertNull(dispatcher.autoReadManagingHandler()); - - dispatcher.enqueue(handler1); - assertEquals(handler1, dispatcher.autoReadManagingHandler()); - - dispatcher.enqueue(handler2); - assertEquals(handler2, dispatcher.autoReadManagingHandler()); - } - - @Test - void shouldForgetAutoReadManagingHandlerWhenItIsRemoved() { - var dispatcher = newDispatcher(); - - var handler1 = mock(ResponseHandler.class); - var handler2 = mock(ResponseHandler.class); - var handler3 = newAutoReadManagingResponseHandler(); - - dispatcher.enqueue(handler1); - dispatcher.enqueue(handler2); - dispatcher.enqueue(handler3); - assertEquals(handler3, dispatcher.autoReadManagingHandler()); - - dispatcher.handleSuccessMessage(emptyMap()); - dispatcher.handleSuccessMessage(emptyMap()); - dispatcher.handleSuccessMessage(emptyMap()); - - assertNull(dispatcher.autoReadManagingHandler()); - } - - @Test - void shouldReEnableAutoReadWhenAutoReadManagingHandlerIsRemoved() { - var channel = newChannelMock(); - var dispatcher = newDispatcher(channel); - - var handler = newAutoReadManagingResponseHandler(); - dispatcher.enqueue(handler); - assertEquals(handler, dispatcher.autoReadManagingHandler()); - verify(handler, never()).disableAutoReadManagement(); - verify(channel.config(), never()).setAutoRead(anyBoolean()); - - dispatcher.handleSuccessMessage(emptyMap()); - - assertNull(dispatcher.autoReadManagingHandler()); - verify(handler).disableAutoReadManagement(); - verify(channel.config()).setAutoRead(anyBoolean()); - } - - @ParameterizedTest - @ValueSource(classes = {SuccessMessage.class, FailureMessage.class, RecordMessage.class, IgnoredMessage.class}) - void shouldCreateChannelActivityLoggerAndLogDebugMessageOnMessageHandling(Class message) { - // GIVEN - var channel = new EmbeddedChannel(); - var logging = mock(LoggingProvider.class); - var logger = mock(System.Logger.class); - when(logger.isLoggable(System.Logger.Level.DEBUG)).thenReturn(true); - when(logging.getLog(InboundMessageDispatcher.class)).thenReturn(logger); - var errorLogger = mock(ChannelErrorLogger.class); - when(logging.getLog(ChannelErrorLogger.class)).thenReturn(errorLogger); - var dispatcher = new InboundMessageDispatcher(channel, logging); - var handler = mock(ResponseHandler.class); - dispatcher.enqueue(handler); - Runnable loggerVerification = () -> {}; - - // WHEN - if (SuccessMessage.class.isAssignableFrom(message)) { - dispatcher.handleSuccessMessage(new HashMap<>()); - loggerVerification = () -> { - verify(logger).isLoggable(System.Logger.Level.DEBUG); - verify(logger) - .log(eq(System.Logger.Level.DEBUG), eq((ResourceBundle) null), anyString(), any(Map.class)); - }; - } else if (FailureMessage.class.isAssignableFrom(message)) { - dispatcher.handleFailureMessage(GqlErrorUtil.gqlError(FAILURE_CODE, FAILURE_MESSAGE)); - loggerVerification = () -> { - verify(logger).isLoggable(System.Logger.Level.DEBUG); - verify(logger) - .log( - eq(System.Logger.Level.DEBUG), - eq((ResourceBundle) null), - anyString(), - anyString(), - anyString()); - }; - } else if (RecordMessage.class.isAssignableFrom(message)) { - dispatcher.handleRecordMessage(new Value[0]); - loggerVerification = () -> { - verify(logger).isLoggable(System.Logger.Level.DEBUG); - verify(logger).log(eq(System.Logger.Level.DEBUG), eq((ResourceBundle) null), anyString(), anyString()); - }; - } else if (IgnoredMessage.class.isAssignableFrom(message)) { - dispatcher.handleIgnoredMessage(); - loggerVerification = () -> { - verify(logger).isLoggable(System.Logger.Level.DEBUG); - verify(logger) - .log(eq(System.Logger.Level.DEBUG), eq((ResourceBundle) null), anyString(), eq((String) null)); - }; - } else { - fail("Unexpected message type parameter provided"); - } - - // THEN - assertTrue(dispatcher.getLog() instanceof ChannelActivityLogger); - assertTrue(dispatcher.getErrorLog() instanceof ChannelErrorLogger); - loggerVerification.run(); - } - - @Test - void shouldCreateChannelErrorLoggerAndLogDebugMessageOnChannelError() { - // GIVEN - var channel = newChannelMock(); - var logging = mock(LoggingProvider.class); - var logger = mock(System.Logger.class); - when(logger.isLoggable(System.Logger.Level.DEBUG)).thenReturn(true); - when(logging.getLog(InboundMessageDispatcher.class)).thenReturn(logger); - var errorLogger = mock(ChannelErrorLogger.class); - when(errorLogger.isLoggable(System.Logger.Level.DEBUG)).thenReturn(true); - when(logging.getLog(ChannelErrorLogger.class)).thenReturn(errorLogger); - var dispatcher = new InboundMessageDispatcher(channel, logging); - var handler = mock(ResponseHandler.class); - dispatcher.enqueue(handler); - var throwable = mock(Throwable.class); - - // WHEN - dispatcher.handleChannelError(throwable); - - // THEN - assertTrue(dispatcher.getLog() instanceof ChannelActivityLogger); - assertTrue(dispatcher.getErrorLog() instanceof ChannelErrorLogger); - verify(errorLogger) - .log( - eq(System.Logger.Level.DEBUG), - eq((ResourceBundle) null), - contains(throwable.getClass().toString()), - eq((String) null)); - } - - private static void verifyFailure(ResponseHandler handler) { - verifyFailure(handler, FAILURE_CODE, FAILURE_MESSAGE, null); - } - - @SuppressWarnings("SameParameterValue") - private static void verifyFailure( - ResponseHandler handler, String code, String message, Class exceptionCls) { - var captor = ArgumentCaptor.forClass(BoltFailureException.class); - verify(handler).onFailure(captor.capture()); - var value = captor.getValue(); - assertEquals(code, value.code()); - assertEquals(message, value.getMessage()); - if (exceptionCls != null) { - assertEquals(exceptionCls, value.getClass()); - } - } - - private static InboundMessageDispatcher newDispatcher() { - return newDispatcher(newChannelMock()); - } - - private static InboundMessageDispatcher newDispatcher(Channel channel) { - return new InboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE); - } - - @SuppressWarnings("unchecked") - private static Channel newChannelMock() { - var channel = mock(Channel.class); - when(channel.id()).thenReturn(DefaultChannelId.newInstance()); - var channelConfig = mock(ChannelConfig.class); - when(channel.config()).thenReturn(channelConfig); - Attribute attribute = mock(Attribute.class); - when(channel.attr(any())).thenReturn(attribute); - return channel; - } - - private static ResponseHandler newAutoReadManagingResponseHandler() { - var handler = mock(ResponseHandler.class); - when(handler.canManageAutoRead()).thenReturn(true); - return handler; - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/InboundMessageHandlerTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/InboundMessageHandlerTest.java deleted file mode 100644 index ba777a6c22..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/InboundMessageHandlerTest.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage.RESET; - -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.handler.codec.DecoderException; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.exception.BoltFailureException; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.FailureMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.IgnoredMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.RecordMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.SuccessMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3.MessageFormatV3; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.ResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.io.MessageToByteBufWriter; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.KnowledgeableMessageFormat; - -class InboundMessageHandlerTest { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private EmbeddedChannel channel; - private InboundMessageDispatcher messageDispatcher; - private MessageToByteBufWriter writer; - - @BeforeEach - void setUp() { - channel = new EmbeddedChannel(); - messageDispatcher = new InboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE); - writer = new MessageToByteBufWriter(new KnowledgeableMessageFormat(false)); - ChannelAttributes.setMessageDispatcher(channel, messageDispatcher); - - var handler = new InboundMessageHandler(new MessageFormatV3(), NoopLoggingProvider.INSTANCE, valueFactory); - channel.pipeline().addFirst(handler); - } - - @AfterEach - void tearDown() { - if (channel != null) { - channel.finishAndReleaseAll(); - } - } - - @Test - void shouldReadSuccessMessage() { - var responseHandler = mock(ResponseHandler.class); - messageDispatcher.enqueue(responseHandler); - - Map metadata = new HashMap<>(); - metadata.put("key1", valueFactory.value(1)); - metadata.put("key2", valueFactory.value(2)); - channel.writeInbound(writer.asByteBuf(new SuccessMessage(metadata))); - - verify(responseHandler).onSuccess(metadata); - } - - @Test - void shouldReadFailureMessage() { - var responseHandler = mock(ResponseHandler.class); - messageDispatcher.enqueue(responseHandler); - - channel.writeInbound(writer.asByteBuf(new FailureMessage("Neo.TransientError.General.ReadOnly", "Hi!"))); - - var captor = ArgumentCaptor.forClass(BoltFailureException.class); - verify(responseHandler).onFailure(captor.capture()); - assertEquals("Neo.TransientError.General.ReadOnly", captor.getValue().code()); - assertEquals("Hi!", captor.getValue().getMessage()); - } - - @Test - void shouldReadRecordMessage() { - var responseHandler = mock(ResponseHandler.class); - messageDispatcher.enqueue(responseHandler); - - var fields = new Value[] {valueFactory.value(1), valueFactory.value(2), valueFactory.value(3)}; - channel.writeInbound(writer.asByteBuf(new RecordMessage(fields))); - - verify(responseHandler).onRecord(fields); - } - - @Test - void shouldReadIgnoredMessage() { - var responseHandler = mock(ResponseHandler.class); - messageDispatcher.enqueue(responseHandler); - - channel.writeInbound(writer.asByteBuf(IgnoredMessage.IGNORED)); - assertEquals(0, messageDispatcher.queuedHandlersCount()); - } - - @Test - void shouldRethrowReadErrors() throws IOException { - var messageFormat = mock(MessageFormat.class); - var reader = mock(MessageFormat.Reader.class); - var error = new RuntimeException("Unable to decode!"); - doThrow(error).when(reader).read(any()); - when(messageFormat.newReader(any(), any())).thenReturn(reader); - - var handler = new InboundMessageHandler(messageFormat, NoopLoggingProvider.INSTANCE, valueFactory); - - channel.pipeline().remove(InboundMessageHandler.class); - channel.pipeline().addLast(handler); - - var e = assertThrows(DecoderException.class, () -> channel.writeInbound(writer.asByteBuf(RESET))); - assertTrue(e.getMessage().startsWith("Failed to read inbound message")); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/MessageDecoderTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/MessageDecoderTest.java deleted file mode 100644 index 356bbb9308..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/inbound/MessageDecoderTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound; - -import static io.netty.buffer.Unpooled.wrappedBuffer; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.TestUtil.assertByteBufEquals; - -import io.netty.channel.embedded.EmbeddedChannel; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; - -class MessageDecoderTest { - private final EmbeddedChannel channel = new EmbeddedChannel(new MessageDecoder()); - - @AfterEach - void tearDown() { - channel.finishAndReleaseAll(); - } - - @Test - void shouldDecodeMessageWithSingleChunk() { - assertFalse(channel.writeInbound(wrappedBuffer(new byte[] {1, 2, 3, 4, 5}))); - assertTrue(channel.writeInbound(wrappedBuffer(new byte[0]))); - assertTrue(channel.finish()); - - assertEquals(1, channel.inboundMessages().size()); - assertByteBufEquals(wrappedBuffer(new byte[] {1, 2, 3, 4, 5}), channel.readInbound()); - } - - @Test - void shouldDecodeMessageWithMultipleChunks() { - assertFalse(channel.writeInbound(wrappedBuffer(new byte[] {1, 2, 3}))); - assertFalse(channel.writeInbound(wrappedBuffer(new byte[] {4, 5}))); - assertFalse(channel.writeInbound(wrappedBuffer(new byte[] {6, 7, 8}))); - assertTrue(channel.writeInbound(wrappedBuffer(new byte[0]))); - assertTrue(channel.finish()); - - assertEquals(1, channel.inboundMessages().size()); - assertByteBufEquals(wrappedBuffer(new byte[] {1, 2, 3, 4, 5, 6, 7, 8}), channel.readInbound()); - } - - @Test - void shouldDecodeMultipleConsecutiveMessages() { - channel.writeInbound(wrappedBuffer(new byte[] {1, 2, 3})); - channel.writeInbound(wrappedBuffer(new byte[0])); - - channel.writeInbound(wrappedBuffer(new byte[] {4, 5})); - channel.writeInbound(wrappedBuffer(new byte[] {6})); - channel.writeInbound(wrappedBuffer(new byte[0])); - - channel.writeInbound(wrappedBuffer(new byte[] {7, 8})); - channel.writeInbound(wrappedBuffer(new byte[] {9, 10})); - channel.writeInbound(wrappedBuffer(new byte[0])); - - assertEquals(3, channel.inboundMessages().size()); - assertByteBufEquals(wrappedBuffer(new byte[] {1, 2, 3}), channel.readInbound()); - assertByteBufEquals(wrappedBuffer(new byte[] {4, 5, 6}), channel.readInbound()); - assertByteBufEquals(wrappedBuffer(new byte[] {7, 8, 9, 10}), channel.readInbound()); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/outbound/ChunkAwareByteBufOutputTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/outbound/ChunkAwareByteBufOutputTest.java deleted file mode 100644 index 9a33bef917..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/outbound/ChunkAwareByteBufOutputTest.java +++ /dev/null @@ -1,479 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.outbound; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.TestUtil.assertByteBufContains; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import java.util.stream.IntStream; -import java.util.stream.Stream; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -class ChunkAwareByteBufOutputTest { - private static Stream testBuffers() { - return IntStream.iterate(1, size -> size * 2).limit(20).mapToObj(Unpooled::buffer); - } - - @Test - void shouldThrowForIllegalMaxChunkSize() { - assertThrows(IllegalArgumentException.class, () -> new ChunkAwareByteBufOutput(-42)); - } - - @Test - void shouldThrowWhenStartedWithNullBuf() { - var output = new ChunkAwareByteBufOutput(16); - assertThrows(NullPointerException.class, () -> output.start(null)); - } - - @Test - void shouldThrowWhenStartedTwice() { - var output = new ChunkAwareByteBufOutput(16); - output.start(mock(ByteBuf.class)); - - assertThrows(IllegalStateException.class, () -> output.start(mock(ByteBuf.class))); - } - - @ParameterizedTest - @MethodSource("testBuffers") - void shouldWriteByteAtTheBeginningOfChunk(ByteBuf buf) { - var output = new ChunkAwareByteBufOutput(16); - - output.start(buf); - output.writeByte((byte) 42); - output.stop(); - - assertByteBufContains(buf, (short) 1, (byte) 42); - } - - @ParameterizedTest - @MethodSource("testBuffers") - void shouldWriteByteWhenCurrentChunkContainsSpace(ByteBuf buf) { - var output = new ChunkAwareByteBufOutput(16); - - output.start(buf); - output.writeByte((byte) 1); - output.writeByte((byte) 2); - output.writeByte((byte) -24); - - output.writeByte((byte) 42); - output.stop(); - - assertByteBufContains(buf, (short) 4, (byte) 1, (byte) 2, (byte) -24, (byte) 42); - } - - @ParameterizedTest - @MethodSource("testBuffers") - void shouldWriteByteWhenCurrentChunkIsFull(ByteBuf buf) { - var output = new ChunkAwareByteBufOutput(5); - - output.start(buf); - output.writeByte((byte) 5); - output.writeByte((byte) 3); - output.writeByte((byte) -5); - - output.writeByte((byte) 42); - output.stop(); - - assertByteBufContains( - buf, - (short) 3, - (byte) 5, - (byte) 3, - (byte) -5, // chunk 1 - (short) 1, - (byte) 42 // chunk 2 - ); - } - - @ParameterizedTest - @MethodSource("testBuffers") - void shouldWriteShortAtTheBeginningOfChunk(ByteBuf buf) { - var output = new ChunkAwareByteBufOutput(10); - - output.start(buf); - output.writeShort(Short.MAX_VALUE); - output.stop(); - - assertByteBufContains(buf, (short) 2, Short.MAX_VALUE); - } - - @ParameterizedTest - @MethodSource("testBuffers") - void shouldWriteShortWhenCurrentChunkContainsSpace(ByteBuf buf) { - var output = new ChunkAwareByteBufOutput(12); - - output.start(buf); - output.writeShort((short) 1); - output.writeShort((short) 42); - output.writeShort((short) 4242); - output.writeShort((short) 4242); - - output.writeShort((short) -30); - output.stop(); - - assertByteBufContains(buf, (short) 10, (short) 1, (short) 42, (short) 4242, (short) 4242, (short) -30); - } - - @ParameterizedTest - @MethodSource("testBuffers") - void shouldWriteShortWhenCurrentChunkIsFull(ByteBuf buf) { - var output = new ChunkAwareByteBufOutput(8); - - output.start(buf); - output.writeShort((short) 14); - output.writeShort((short) -99); - output.writeShort((short) 202); - - output.writeShort(Short.MIN_VALUE); - output.stop(); - - assertByteBufContains( - buf, - (short) 6, - (short) 14, - (short) -99, - (short) 202, // chunk 1 - (short) 2, - Short.MIN_VALUE // chunk 2 - ); - } - - @ParameterizedTest - @MethodSource("testBuffers") - void shouldWriteIntAtTheBeginningOfChunk(ByteBuf buf) { - var output = new ChunkAwareByteBufOutput(18); - - output.start(buf); - output.writeInt(73649); - output.stop(); - - assertByteBufContains(buf, (short) 4, 73649); - } - - @ParameterizedTest - @MethodSource("testBuffers") - void shouldWriteIntWhenCurrentChunkContainsSpace(ByteBuf buf) { - var output = new ChunkAwareByteBufOutput(40); - - output.start(buf); - output.writeInt(Integer.MAX_VALUE); - output.writeInt(20); - output.writeInt(-173); - - output.writeInt(Integer.MIN_VALUE); - output.stop(); - - assertByteBufContains(buf, (short) 16, Integer.MAX_VALUE, 20, -173, Integer.MIN_VALUE); - } - - @ParameterizedTest - @MethodSource("testBuffers") - void shouldWriteIntWhenCurrentChunkIsFull(ByteBuf buf) { - var output = new ChunkAwareByteBufOutput(27); - - output.start(buf); - output.writeInt(42); - output.writeInt(-73467193); - output.writeInt(373); - output.writeInt(-93); - output.writeInt(1312345); - output.writeInt(785); - - output.writeInt(42); - output.stop(); - - assertByteBufContains( - buf, - (short) 24, - 42, - -73467193, - 373, - -93, - 1312345, - 785, // chunk 1 - (short) 4, - 42 // chunk 2 - ); - } - - @ParameterizedTest - @MethodSource("testBuffers") - void shouldWriteLongAtTheBeginningOfChunk(ByteBuf buf) { - var output = new ChunkAwareByteBufOutput(12); - - output.start(buf); - output.writeLong(15); - output.stop(); - - assertByteBufContains(buf, (short) 8, 15L); - } - - @ParameterizedTest - @MethodSource("testBuffers") - void shouldWriteLongWhenCurrentChunkContainsSpace(ByteBuf buf) { - var output = new ChunkAwareByteBufOutput(34); - - output.start(buf); - output.writeLong(Long.MAX_VALUE); - output.writeLong(-1); - output.writeLong(-100); - - output.writeLong(Long.MIN_VALUE / 2); - output.stop(); - - assertByteBufContains(buf, (short) 32, Long.MAX_VALUE, -1L, -100L, Long.MIN_VALUE / 2); - } - - @ParameterizedTest - @MethodSource("testBuffers") - void shouldWriteLongWhenCurrentChunkIsFull(ByteBuf buf) { - var output = new ChunkAwareByteBufOutput(38); - - output.start(buf); - output.writeLong(12); - output.writeLong(8741); - output.writeLong(2314); - output.writeLong(-85793); - - output.writeLong(-57999999); - output.stop(); - - assertByteBufContains( - buf, - (short) 32, - 12L, - 8741L, - 2314L, - -85793L, // chunk 1 - (short) 8, - -57999999L // chunk 2 - ); - } - - @ParameterizedTest - @MethodSource("testBuffers") - void shouldWriteDoubleAtTheBeginningOfChunk(ByteBuf buf) { - var output = new ChunkAwareByteBufOutput(10); - - output.start(buf); - output.writeDouble(12.99937); - output.stop(); - - assertByteBufContains(buf, (short) 8, 12.99937D); - } - - @ParameterizedTest - @MethodSource("testBuffers") - void shouldWriteDoubleWhenCurrentChunkContainsSpace(ByteBuf buf) { - var output = new ChunkAwareByteBufOutput(18); - - output.start(buf); - output.writeDouble(-5); - - output.writeDouble(991.3333); - output.stop(); - - assertByteBufContains(buf, (short) 16, -5D, 991.3333D); - } - - @ParameterizedTest - @MethodSource("testBuffers") - void shouldWriteDoubleWhenCurrentChunkIsFull(ByteBuf buf) { - var output = new ChunkAwareByteBufOutput(20); - - output.start(buf); - output.writeDouble(1839); - output.writeDouble(5710923.34873); - - output.writeDouble(-47389.333399); - output.stop(); - - assertByteBufContains( - buf, - (short) 16, - 1839D, - 5710923.34873D, // chunk 1 - (short) 8, - -47389.333399D // chunk 2 - ); - } - - @ParameterizedTest - @MethodSource("testBuffers") - void shouldWriteBytesAtTheBeginningOfChunk(ByteBuf buf) { - var output = new ChunkAwareByteBufOutput(10); - - output.start(buf); - output.writeBytes(new byte[] {1, 2, 3, -1, -2, -3, 127}); - output.stop(); - - assertByteBufContains( - buf, (short) 7, (byte) 1, (byte) 2, (byte) 3, (byte) -1, (byte) -2, (byte) -3, (byte) 127); - } - - @ParameterizedTest - @MethodSource("testBuffers") - void shouldWriteBytesWhenCurrentChunkContainsSpace(ByteBuf buf) { - var output = new ChunkAwareByteBufOutput(13); - - output.start(buf); - output.writeBytes(new byte[] {9, 8, -10}); - output.writeBytes(new byte[] {127, 126, -128, -126}); - output.writeBytes(new byte[] {0, 99}); - - output.writeBytes(new byte[] {-42, 42}); - output.stop(); - - assertByteBufContains( - buf, - (short) 11, - (byte) 9, - (byte) 8, - (byte) -10, - (byte) 127, - (byte) 126, - (byte) -128, - (byte) -126, - (byte) 0, - (byte) 99, - (byte) -42, - (byte) 42); - } - - @ParameterizedTest - @MethodSource("testBuffers") - void shouldWriteBytesWhenCurrentChunkIsFull(ByteBuf buf) { - var output = new ChunkAwareByteBufOutput(9); - - output.start(buf); - output.writeBytes(new byte[] {1, 2}); - output.writeBytes(new byte[] {3, 4, 5}); - output.writeBytes(new byte[] {10}); - - output.writeBytes(new byte[] {-1, -42, -43}); - output.stop(); - - assertByteBufContains( - buf, - (short) 7, - (byte) 1, - (byte) 2, - (byte) 3, - (byte) 4, - (byte) 5, - (byte) 10, - (byte) -1, // chunk 1 - (short) 2, - (byte) -42, - (byte) -43 // chunk 2 - ); - } - - @ParameterizedTest - @MethodSource("testBuffers") - void shouldWriteBytesThatSpanMultipleChunks(ByteBuf buf) { - var output = new ChunkAwareByteBufOutput(7); - - output.start(buf); - output.writeBytes(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}); - output.stop(); - - assertByteBufContains( - buf, - (short) 5, - (byte) 1, - (byte) 2, - (byte) 3, - (byte) 4, - (byte) 5, // chunk 1 - (short) 5, - (byte) 6, - (byte) 7, - (byte) 8, - (byte) 9, - (byte) 10, // chunk 2 - (short) 5, - (byte) 11, - (byte) 12, - (byte) 13, - (byte) 14, - (byte) 15, // chunk 3 - (short) 3, - (byte) 16, - (byte) 17, - (byte) 18 // chunk 4 - ); - } - - @ParameterizedTest - @MethodSource("testBuffers") - void shouldWriteDataToMultipleChunks(ByteBuf buf) { - var output = new ChunkAwareByteBufOutput(13); - - output.start(buf); - output.writeDouble(12.3); - output.writeByte((byte) 42); - output.writeInt(-10); - output.writeInt(99); - output.writeLong(99); - output.writeBytes(new byte[] {9, 8, 7, 6}); - output.writeDouble(0.333); - output.writeShort((short) 0); - output.writeShort((short) 1); - output.writeInt(12345); - output.writeBytes(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}); - output.stop(); - - assertByteBufContains( - buf, - (short) 9, - 12.3D, - (byte) 42, // chunk 1 - (short) 8, - -10, - 99, // chunk 2 - (short) 11, - 99L, - (byte) 9, - (byte) 8, - (byte) 7, // chunk 3 - (short) 11, - (byte) 6, - 0.333D, - (short) 0, // chunk 4 - (short) 11, - (short) 1, - 12345, - (byte) 1, - (byte) 2, - (byte) 3, - (byte) 4, - (byte) 5, // chunk 5 - (short) 5, - (byte) 6, - (byte) 7, - (byte) 8, - (byte) 9, - (byte) 10 // chunk 6 - ); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/outbound/OutboundMessageHandlerTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/outbound/OutboundMessageHandlerTest.java deleted file mode 100644 index 665327b1ae..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/async/outbound/OutboundMessageHandlerTest.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.async.outbound; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullAllMessage.PULL_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.TestUtil.assertByteBufContains; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.embedded.EmbeddedChannel; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3.BoltProtocolV3; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3.MessageFormatV3; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -class OutboundMessageHandlerTest { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private final EmbeddedChannel channel = new EmbeddedChannel(); - - @BeforeEach - void setUp() { - ChannelAttributes.setMessageDispatcher( - channel, new InboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE)); - } - - @AfterEach - void tearDown() { - channel.finishAndReleaseAll(); - } - - @Test - void shouldOutputByteBufAsWrittenByWriterAndMessageBoundary() { - var messageFormat = mockMessageFormatWithWriter(1, 2, 3, 4, 5); - var handler = newHandler(messageFormat); - channel.pipeline().addLast(handler); - - // do not care which message, writer will return predefined bytes anyway - assertTrue(channel.writeOutbound(PULL_ALL)); - assertTrue(channel.finish()); - - assertEquals(1, channel.outboundMessages().size()); - - ByteBuf buf = channel.readOutbound(); - assertByteBufContains( - buf, - (short) 5, - (byte) 1, - (byte) 2, - (byte) 3, - (byte) 4, - (byte) 5, // message body - (byte) 0, - (byte) 0 // message boundary - ); - } - - @Test - void shouldSupportByteArraysByDefault() { - var handler = newHandler(new MessageFormatV3()); - channel.pipeline().addLast(handler); - - Map params = new HashMap<>(); - params.put("array", valueFactory.value(new byte[] {1, 2, 3})); - - assertTrue(channel.writeOutbound(new BoltProtocolV3.Query("RETURN 1", params))); - assertTrue(channel.finish()); - } - - private static MessageFormat mockMessageFormatWithWriter( - @SuppressWarnings("SameParameterValue") final int... bytesToWrite) { - var messageFormat = mock(MessageFormat.class); - - when(messageFormat.newWriter(any(PackOutput.class), any())).then(invocation -> { - PackOutput output = invocation.getArgument(0); - return mockWriter(output, bytesToWrite); - }); - - return messageFormat; - } - - private static MessageFormat.Writer mockWriter(final PackOutput output, final int... bytesToWrite) - throws IOException { - var writer = mock(MessageFormat.Writer.class); - - doAnswer(invocation -> { - for (var b : bytesToWrite) { - output.writeByte((byte) b); - } - return writer; - }) - .when(writer) - .write(any(Message.class)); - - return writer; - } - - private static OutboundMessageHandler newHandler(MessageFormat messageFormat) { - return new OutboundMessageHandler(messageFormat, NoopLoggingProvider.INSTANCE, valueFactory); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/CommitTxResponseHandlerTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/CommitTxResponseHandlerTest.java deleted file mode 100644 index 727448a2f9..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/CommitTxResponseHandlerTest.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.handlers; - -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.TestUtil.await; - -import java.util.concurrent.CompletableFuture; -import org.junit.jupiter.api.Test; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; - -class CommitTxResponseHandlerTest { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private final CompletableFuture future = new CompletableFuture<>(); - private final CommitTxResponseHandler handler = new CommitTxResponseHandler(future); - - @Test - void shouldHandleSuccessWithoutBookmark() { - handler.onSuccess(emptyMap()); - - assertNull(await(future)); - } - - @Test - void shouldHandleSuccessWithBookmark() { - var bookmarkString = "neo4j:bookmark:v1:tx12345"; - - handler.onSuccess(singletonMap("bookmark", valueFactory.value(bookmarkString))); - - assertEquals(bookmarkString, await(future)); - } - - @Test - void shouldHandleFailure() { - var error = new RuntimeException("Hello"); - - handler.onFailure(error); - - var receivedError = assertThrows(RuntimeException.class, () -> await(future)); - assertEquals(error, receivedError); - } - - @Test - void shouldFailToHandleRecord() { - assertThrows(UnsupportedOperationException.class, () -> handler.onRecord(new Value[] {valueFactory.value(42)})); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/HelloResponseHandlerTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/HelloResponseHandlerTest.java deleted file mode 100644 index 29e86937e6..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/HelloResponseHandlerTest.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.handlers; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.mock; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.connectionId; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.connectionReadTimeout; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.serverAgent; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setMessageDispatcher; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.outbound.OutboundMessageHandler.NAME; - -import io.netty.channel.embedded.EmbeddedChannel; -import java.time.Clock; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.TimeUnit; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.exception.BoltUntrustedServerException; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.ChannelErrorHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.outbound.OutboundMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3.MessageFormatV3; - -class HelloResponseHandlerTest { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private static final String SERVER_AGENT = "Neo4j/4.4.0"; - - private final EmbeddedChannel channel = new EmbeddedChannel(); - - @BeforeEach - void setUp() { - setMessageDispatcher(channel, new InboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE)); - var pipeline = channel.pipeline(); - pipeline.addLast( - NAME, new OutboundMessageHandler(new MessageFormatV3(), NoopLoggingProvider.INSTANCE, valueFactory)); - pipeline.addLast(new ChannelErrorHandler(NoopLoggingProvider.INSTANCE)); - } - - @AfterEach - void tearDown() { - channel.finishAndReleaseAll(); - } - - @Test - void shouldSetServerAgentOnChannel() { - var agentFuture = new CompletableFuture(); - var latestAuth = new CompletableFuture(); - var handler = new HelloResponseHandler(agentFuture, channel, mock(Clock.class), latestAuth); - - var metadata = metadata(SERVER_AGENT, "bolt-1"); - handler.onSuccess(metadata); - - assertTrue(agentFuture.isDone() && !agentFuture.isCompletedExceptionally() && !agentFuture.isCancelled()); - assertEquals(SERVER_AGENT, serverAgent(channel)); - } - - @Test - void shouldThrowWhenServerVersionNotReturned() { - var agentFuture = new CompletableFuture(); - var latestAuth = new CompletableFuture(); - var handler = new HelloResponseHandler(agentFuture, channel, mock(Clock.class), latestAuth); - - var metadata = metadata(null, "bolt-1"); - assertThrows(BoltUntrustedServerException.class, () -> handler.onSuccess(metadata)); - - assertTrue(agentFuture.isCompletedExceptionally()); // initialization failed - assertTrue(channel.closeFuture().isDone()); // channel was closed - } - - @Test - void shouldThrowWhenServerVersionIsNull() { - var agentFuture = new CompletableFuture(); - var latestAuth = new CompletableFuture(); - var handler = new HelloResponseHandler(agentFuture, channel, mock(Clock.class), latestAuth); - - var metadata = metadata(valueFactory.value(null), "bolt-x"); - assertThrows(BoltUntrustedServerException.class, () -> handler.onSuccess(metadata)); - - assertTrue(agentFuture.isCompletedExceptionally()); // initialization failed - assertTrue(channel.closeFuture().isDone()); // channel was closed - } - - @Test - void shouldThrowWhenServerAgentIsUnrecognised() { - var agentFuture = new CompletableFuture(); - var latestAuth = new CompletableFuture(); - var handler = new HelloResponseHandler(agentFuture, channel, mock(Clock.class), latestAuth); - - var metadata = metadata("WrongServerVersion", "bolt-x"); - assertThrows(BoltUntrustedServerException.class, () -> handler.onSuccess(metadata)); - - assertTrue(agentFuture.isCompletedExceptionally()); // initialization failed - assertTrue(channel.closeFuture().isDone()); // channel was closed - } - - @Test - void shouldSetConnectionIdOnChannel() { - var agentFuture = new CompletableFuture(); - var latestAuth = new CompletableFuture(); - var handler = new HelloResponseHandler(agentFuture, channel, mock(Clock.class), latestAuth); - - var metadata = metadata(SERVER_AGENT, "bolt-42"); - handler.onSuccess(metadata); - - assertTrue(agentFuture.isDone() && !agentFuture.isCompletedExceptionally() && !agentFuture.isCancelled()); - assertEquals("bolt-42", connectionId(channel)); - } - - @Test - void shouldThrowWhenConnectionIdNotReturned() { - var agentFuture = new CompletableFuture(); - var latestAuth = new CompletableFuture(); - var handler = new HelloResponseHandler(agentFuture, channel, mock(Clock.class), latestAuth); - - var metadata = metadata(SERVER_AGENT, null); - assertThrows(IllegalStateException.class, () -> handler.onSuccess(metadata)); - - assertTrue(agentFuture.isCompletedExceptionally()); // initialization failed - assertTrue(channel.closeFuture().isDone()); // channel was closed - } - - @Test - void shouldThrowWhenConnectionIdIsNull() { - var agentFuture = new CompletableFuture(); - var latestAuth = new CompletableFuture(); - var handler = new HelloResponseHandler(agentFuture, channel, mock(Clock.class), latestAuth); - - var metadata = metadata(SERVER_AGENT, valueFactory.value(null)); - assertThrows(IllegalStateException.class, () -> handler.onSuccess(metadata)); - - assertTrue(agentFuture.isCompletedExceptionally()); // initialization failed - assertTrue(channel.closeFuture().isDone()); // channel was closed - } - - @Test - void shouldCloseChannelOnFailure() throws Exception { - var agentFuture = new CompletableFuture(); - var latestAuth = new CompletableFuture(); - var handler = new HelloResponseHandler(agentFuture, channel, mock(Clock.class), latestAuth); - - var error = new RuntimeException("Hi!"); - handler.onFailure(error); - - var channelCloseFuture = channel.closeFuture(); - channelCloseFuture.await(5, TimeUnit.SECONDS); - - assertTrue(channelCloseFuture.isSuccess()); - assertTrue(agentFuture.isCompletedExceptionally()); - assertEquals( - error, - assertThrows(CompletionException.class, agentFuture::join).getCause()); - } - - @Test - void shouldNotThrowWhenConfigurationHintsAreAbsent() { - var agentFuture = new CompletableFuture(); - var latestAuth = new CompletableFuture(); - var handler = new HelloResponseHandler(agentFuture, channel, mock(Clock.class), latestAuth); - - var metadata = metadata(SERVER_AGENT, "bolt-x"); - handler.onSuccess(metadata); - - assertTrue(agentFuture.isDone() && !agentFuture.isCompletedExceptionally() && !agentFuture.isCancelled()); - assertFalse(channel.closeFuture().isDone()); - } - - @Test - void shouldNotThrowWhenConfigurationHintsAreEmpty() { - var agentFuture = new CompletableFuture(); - var latestAuth = new CompletableFuture(); - var handler = new HelloResponseHandler(agentFuture, channel, mock(Clock.class), latestAuth); - - var metadata = metadata(SERVER_AGENT, "bolt-x", valueFactory.value(new HashMap<>())); - handler.onSuccess(metadata); - - assertTrue(agentFuture.isDone() && !agentFuture.isCompletedExceptionally() && !agentFuture.isCancelled()); - assertFalse(channel.closeFuture().isDone()); - } - - @Test - void shouldNotThrowWhenConfigurationHintsAreNull() { - var agentFuture = new CompletableFuture(); - var latestAuth = new CompletableFuture(); - var handler = new HelloResponseHandler(agentFuture, channel, mock(Clock.class), latestAuth); - - var metadata = metadata(SERVER_AGENT, "bolt-x", valueFactory.value(null)); - handler.onSuccess(metadata); - - assertTrue(agentFuture.isDone() && !agentFuture.isCompletedExceptionally() && !agentFuture.isCancelled()); - assertFalse(channel.closeFuture().isDone()); - } - - @Test - void shouldSetConnectionTimeoutHint() { - var agentFuture = new CompletableFuture(); - var latestAuth = new CompletableFuture(); - var handler = new HelloResponseHandler(agentFuture, channel, mock(Clock.class), latestAuth); - - var timeout = 15L; - Map hints = new HashMap<>(); - hints.put(HelloResponseHandler.CONNECTION_RECEIVE_TIMEOUT_SECONDS_KEY, valueFactory.value(timeout)); - var metadata = metadata(SERVER_AGENT, "bolt-x", valueFactory.value(hints)); - handler.onSuccess(metadata); - - assertEquals(timeout, connectionReadTimeout(channel).orElse(null)); - assertTrue(agentFuture.isDone() && !agentFuture.isCompletedExceptionally() && !agentFuture.isCancelled()); - assertFalse(channel.closeFuture().isDone()); - } - - private static Map metadata(Object version, Object connectionId) { - return metadata(version, connectionId, null); - } - - private static Map metadata(Object version, Object connectionId, Value hints) { - Map result = new HashMap<>(); - - if (version == null) { - result.put("server", null); - } else if (version instanceof Value && ((Value) version).isNull()) { - result.put("server", valueFactory.value(null)); - } else { - result.put("server", valueFactory.value(version.toString())); - } - - if (connectionId == null) { - result.put("connection_id", null); - } else { - result.put("connection_id", valueFactory.value(connectionId)); - } - result.put(HelloResponseHandler.CONFIGURATION_HINTS_KEY, hints); - - return result; - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/ResetResponseHandlerTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/ResetResponseHandlerTest.java deleted file mode 100644 index ed8ff352b9..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/ResetResponseHandlerTest.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.handlers; - -import static java.util.Collections.emptyMap; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.concurrent.CompletableFuture; -import org.junit.jupiter.api.Test; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; - -class ResetResponseHandlerTest { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - - @Test - void shouldCompleteFutureOnSuccess() throws Exception { - var future = new CompletableFuture(); - var handler = newHandler(future); - - assertFalse(future.isDone()); - - handler.onSuccess(emptyMap()); - - assertTrue(future.isDone()); - assertNull(future.get()); - } - - @Test - void shouldCompleteFutureOnFailure() { - var future = new CompletableFuture(); - var handler = newHandler(future); - - assertFalse(future.isDone()); - - handler.onFailure(new RuntimeException()); - - assertTrue(future.isCompletedExceptionally()); - } - - @Test - void shouldThrowWhenOnRecord() { - var handler = newHandler(new CompletableFuture<>()); - - assertThrows( - UnsupportedOperationException.class, - () -> handler.onRecord( - new Value[] {valueFactory.value(1), valueFactory.value(2), valueFactory.value(3)})); - } - - private static ResetResponseHandler newHandler(CompletableFuture future) { - return new ResetResponseHandler(future); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/RouteMessageResponseHandlerTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/RouteMessageResponseHandlerTest.java deleted file mode 100644 index f60db3a25e..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/RouteMessageResponseHandlerTest.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.handlers; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import org.junit.jupiter.api.Test; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; - -class RouteMessageResponseHandlerTest { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - - @Test - void onSuccessShouldSuccessFullyCompleteFutureWithRoutingTable() { - var completableFuture = new CompletableFuture>(); - var responseHandler = new RouteMessageResponseHandler(completableFuture, valueFactory); - var routingTable = getRoutingTable(); - var metadata = getMetadataWithRoutingTable(routingTable); - - responseHandler.onSuccess(metadata); - - assertEquals(routingTable, completableFuture.getNow(null)); - } - - @Test - void onSuccessShouldExceptionallyCompleteFutureWhenMetadataDoesNotHaveRoutingTable() { - var completableFuture = new CompletableFuture>(); - var responseHandler = new RouteMessageResponseHandler(completableFuture, valueFactory); - Map metadata = new HashMap<>(); - - responseHandler.onSuccess(metadata); - - assertThrows(CompletionException.class, () -> completableFuture.getNow(null)); - } - - @Test - void onFailureShouldCompleteExceptionallyWithTheOriginalException() { - var completableFuture = new CompletableFuture>(); - var responseHandler = new RouteMessageResponseHandler(completableFuture, valueFactory); - var expectedException = new RuntimeException("Test exception"); - - responseHandler.onFailure(expectedException); - - assertTrue(completableFuture.isCompletedExceptionally()); - completableFuture.handle((value, ex) -> { - assertNull(value); - assertEquals(expectedException, ex); - return null; - }); - } - - @Test - void onRecordShouldThrowUnsupportedOperation() { - var completableFuture = new CompletableFuture>(); - var responseHandler = new RouteMessageResponseHandler(completableFuture, valueFactory); - - responseHandler.onRecord(new Value[0]); - - assertTrue(completableFuture.isCompletedExceptionally()); - completableFuture.handle((value, ex) -> { - assertNull(value); - assertEquals(UnsupportedOperationException.class, ex.getClass()); - return null; - }); - } - - private Map getMetadataWithRoutingTable(Map routingTable) { - Map metadata = new HashMap<>(); - metadata.put("rt", valueFactory.value(routingTable)); - return metadata; - } - - private Map getRoutingTable() { - Map routingTable = new HashMap<>(); - routingTable.put("ttl", valueFactory.value(300)); - routingTable.put("addresses", valueFactory.value(new ArrayList<>())); - return routingTable; - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/RunResponseHandlerTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/RunResponseHandlerTest.java deleted file mode 100644 index 43080169c4..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/handlers/RunResponseHandlerTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.handlers; - -import static java.util.Collections.emptyMap; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import org.junit.jupiter.api.Test; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3.BoltProtocolV3; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.MetadataExtractor; - -class RunResponseHandlerTest { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - - @Test - void shouldNotifyRunFutureOnSuccess() { - var runFuture = new CompletableFuture(); - var handler = newHandler(runFuture); - - assertFalse(runFuture.isDone()); - handler.onSuccess(emptyMap()); - - assertTrue(runFuture.isDone() && !runFuture.isCompletedExceptionally() && !runFuture.isCancelled()); - } - - @Test - void shouldNotifyRunFutureOnFailure() { - var runFuture = new CompletableFuture(); - var handler = newHandler(runFuture); - - assertFalse(runFuture.isDone()); - var exception = new RuntimeException(); - handler.onFailure(exception); - - assertTrue(runFuture.isCompletedExceptionally()); - var executionException = assertThrows(ExecutionException.class, runFuture::get); - assertEquals(exception, executionException.getCause()); - } - - @Test - void shouldThrowOnRecord() { - var handler = newHandler(); - - assertThrows( - UnsupportedOperationException.class, - () -> handler.onRecord( - new Value[] {valueFactory.value("a"), valueFactory.value("b"), valueFactory.value("c")})); - } - - private static RunResponseHandler newHandler() { - return newHandler(BoltProtocolV3.METADATA_EXTRACTOR); - } - - private static RunResponseHandler newHandler(CompletableFuture runFuture) { - return newHandler(runFuture, BoltProtocolV3.METADATA_EXTRACTOR); - } - - private static RunResponseHandler newHandler( - @SuppressWarnings("SameParameterValue") MetadataExtractor metadataExtractor) { - return newHandler(new CompletableFuture<>(), metadataExtractor); - } - - private static RunResponseHandler newHandler( - CompletableFuture runFuture, MetadataExtractor metadataExtractor) { - return new RunResponseHandler(runFuture, metadataExtractor); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/logging/ChannelActivityLoggerTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/logging/ChannelActivityLoggerTest.java deleted file mode 100644 index dc30084066..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/logging/ChannelActivityLoggerTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.logging; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import io.netty.channel.embedded.EmbeddedChannel; -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; - -class ChannelActivityLoggerTest { - @Test - void shouldReformatWhenChannelIsNull() { - var activityLogger = new ChannelActivityLogger(null, NoopLoggingProvider.INSTANCE, getClass()); - - var reformatted = activityLogger.reformat("Hello!"); - - assertEquals("Hello!", reformatted); - } - - @Test - void shouldReformatWithChannelId() { - var channel = new EmbeddedChannel(); - var activityLogger = new ChannelActivityLogger(channel, NoopLoggingProvider.INSTANCE, getClass()); - - var reformatted = activityLogger.reformat("Hello!"); - - assertEquals("[0x" + channel.id() + "][][] Hello!", reformatted); - } - - @Test - void shouldReformatWithChannelIdAndServerAddress() { - var channel = new EmbeddedChannel(); - ChannelAttributes.setServerAddress(channel, new BoltServerAddress("somewhere", 1234)); - var activityLogger = new ChannelActivityLogger(channel, NoopLoggingProvider.INSTANCE, getClass()); - - var reformatted = activityLogger.reformat("Hello!"); - - assertEquals("[0x" + channel.id() + "][somewhere:1234][] Hello!", reformatted); - } - - @Test - void shouldReformatWithChannelIdAndConnectionId() { - var channel = new EmbeddedChannel(); - ChannelAttributes.setConnectionId(channel, "bolt-12345"); - var activityLogger = new ChannelActivityLogger(channel, NoopLoggingProvider.INSTANCE, getClass()); - - var reformatted = activityLogger.reformat("Hello!"); - - assertEquals("[0x" + channel.id() + "][][bolt-12345] Hello!", reformatted); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/BoltProtocolTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/BoltProtocolTest.java deleted file mode 100644 index a3d0204f3b..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/BoltProtocolTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging; - -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setProtocolVersion; - -import io.netty.channel.embedded.EmbeddedChannel; -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.exception.BoltClientException; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3.BoltProtocolV3; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v42.BoltProtocolV42; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v43.BoltProtocolV43; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v44.BoltProtocolV44; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v5.BoltProtocolV5; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v51.BoltProtocolV51; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v52.BoltProtocolV52; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v53.BoltProtocolV53; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v54.BoltProtocolV54; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v55.BoltProtocolV55; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v56.BoltProtocolV56; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v57.BoltProtocolV57; - -class BoltProtocolTest { - @Test - void shouldCreateProtocolForKnownVersions() { - assertAll( - () -> assertInstanceOf(BoltProtocolV3.class, BoltProtocol.forVersion(BoltProtocolV3.VERSION)), - () -> assertInstanceOf(BoltProtocolV42.class, BoltProtocol.forVersion(BoltProtocolV42.VERSION)), - () -> assertInstanceOf(BoltProtocolV43.class, BoltProtocol.forVersion(BoltProtocolV43.VERSION)), - () -> assertInstanceOf(BoltProtocolV44.class, BoltProtocol.forVersion(BoltProtocolV44.VERSION)), - () -> assertInstanceOf(BoltProtocolV5.class, BoltProtocol.forVersion(BoltProtocolV5.VERSION)), - () -> assertInstanceOf(BoltProtocolV51.class, BoltProtocol.forVersion(BoltProtocolV51.VERSION)), - () -> assertInstanceOf(BoltProtocolV52.class, BoltProtocol.forVersion(BoltProtocolV52.VERSION)), - () -> assertInstanceOf(BoltProtocolV53.class, BoltProtocol.forVersion(BoltProtocolV53.VERSION)), - () -> assertInstanceOf(BoltProtocolV54.class, BoltProtocol.forVersion(BoltProtocolV54.VERSION)), - () -> assertInstanceOf(BoltProtocolV55.class, BoltProtocol.forVersion(BoltProtocolV55.VERSION)), - () -> assertInstanceOf(BoltProtocolV56.class, BoltProtocol.forVersion(BoltProtocolV56.VERSION)), - () -> assertInstanceOf(BoltProtocolV57.class, BoltProtocol.forVersion(BoltProtocolV57.VERSION))); - } - - @Test - void shouldThrowForUnknownVersion() { - assertAll( - () -> assertThrows( - BoltClientException.class, () -> BoltProtocol.forVersion(new BoltProtocolVersion(42, 0))), - () -> assertThrows( - BoltClientException.class, () -> BoltProtocol.forVersion(new BoltProtocolVersion(142, 0))), - () -> assertThrows( - BoltClientException.class, () -> BoltProtocol.forVersion(new BoltProtocolVersion(-1, 0)))); - } - - @Test - void shouldThrowForChannelWithUnknownProtocolVersion() { - var channel = new EmbeddedChannel(); - setProtocolVersion(channel, new BoltProtocolVersion(42, 0)); - - assertThrows(BoltClientException.class, () -> BoltProtocol.forChannel(channel)); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/BoltProtocolVersionTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/BoltProtocolVersionTest.java deleted file mode 100644 index 7694e82ef2..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/BoltProtocolVersionTest.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; - -class BoltProtocolVersionTest { - - @ParameterizedTest(name = "V{0}.{1}") - @CsvSource({"3, 0", "4, 0", "4, 1", "4, 2", "100, 100", "255, 255", "0, 0"}) - void shouldParseVersion(int major, int minor) { - var protocolVersion = new BoltProtocolVersion(major, minor); - - var testVersion = BoltProtocolVersion.fromRawBytes(protocolVersion.toInt()); - - assertEquals(major, testVersion.getMajorVersion()); - assertEquals(minor, testVersion.getMinorVersion()); - } - - @ParameterizedTest(name = "V{0}.{1} comparedTo V{2}.{3}") - @CsvSource({"1, 3, 25, 21, -1", "4, 0, 4, 0, 0", "4, 1, 4, 0, 1", "0, 1, 0, 2, -1"}) - void shouldCompareTo(int majorA, int minorA, int majorB, int minorB, int expectedResult) { - var versionA = new BoltProtocolVersion(majorA, minorA); - var versionB = new BoltProtocolVersion(majorB, minorB); - - assertEquals(expectedResult, versionA.compareTo(versionB)); - } - - @ParameterizedTest(name = "V{0}.{1} toIntRange V{2}.{3}") - @CsvSource({ - "1, 0, 1, 0, 0x000001", - "4, 3, 4, 2, 0x010304", - "4, 3, 4, 1, 0x020304", - "4, 3, 4, 0, 0x030304", - "100, 100, 100, 0, 0x646464", - "255, 255, 255, 0, 0xFFFFFF" - }) - void shouldOutputCorrectIntRange(int majorA, int minorA, int majorB, int minorB, int expectedResult) { - var versionA = new BoltProtocolVersion(majorA, minorA); - var versionB = new BoltProtocolVersion(majorB, minorB); - - assertEquals(expectedResult, versionA.toIntRange(versionB)); - } - - @ParameterizedTest(name = "V{0}.{1} toIntRange V{2}.{3}") - @CsvSource({"1, 0, 2, 0", "2, 0, 1, 0", "4, 3, 4, 5", "4, 6, 3, 7", "3, 7, 4, 6", "255, 255, 100, 0"}) - void shouldThrowsIllegalArgumentExceptionForIncorrectIntRange(int majorA, int minorA, int majorB, int minorB) { - var versionA = new BoltProtocolVersion(majorA, minorA); - var versionB = new BoltProtocolVersion(majorB, minorB); - - assertThrows(IllegalArgumentException.class, () -> versionA.toIntRange(versionB)); - } - - @Test - void shouldOutputCorrectLongFormatForMajorVersionOnly() { - var version = new BoltProtocolVersion(4, 0); - assertEquals(4L, version.toInt()); - } - - @Test - void shouldOutputCorrectLongFormatForMajorAndMinorVersion() { - var version = new BoltProtocolVersion(4, 1); - assertEquals(260L, version.toInt()); - } - - @Test - void shouldOutputFormattedString() { - var version = new BoltProtocolVersion(4, 1); - - assertEquals("4.1", version.toString()); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/MessageFormatTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/MessageFormatTest.java deleted file mode 100644 index 6bc629afae..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/MessageFormatTest.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging; - -import static java.util.Arrays.asList; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.messageDispatcher; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes.setMessageDispatcher; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.embedded.EmbeddedChannel; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import org.junit.jupiter.api.Test; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.exception.BoltClientException; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.BoltProtocolUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelPipelineBuilderImpl; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.outbound.ChunkAwareByteBufOutput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonValueUnpacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.FailureMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.IgnoredMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.RecordMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.SuccessMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3.MessageFormatV3; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackStream; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.ResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.KnowledgeableMessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.MemorizingInboundMessageDispatcher; - -class MessageFormatTest { - private static final TestValueFactory valueFactory = TestValueFactory.INSTANCE; - public final MessageFormat format = new MessageFormatV3(); - - @Test - void shouldUnpackAllResponses() { - assertSerializes(new FailureMessage("Hello", "World!")); - assertSerializes(IgnoredMessage.IGNORED); - assertSerializes(new RecordMessage(new Value[] {valueFactory.value(1337L)})); - assertSerializes(new SuccessMessage(new HashMap<>())); - } - - @Test - void shouldPackUnpackValidValues() { - assertSerializesValue( - valueFactory.value(Map.of("cat", valueFactory.value(null), "dog", valueFactory.value(null)))); - assertSerializesValue( - valueFactory.value(Map.of("k", valueFactory.value(12), "a", valueFactory.value("banana")))); - assertSerializesValue(valueFactory.value(asList("k", 12, "a", "banana"))); - } - - @Test - void shouldUnpackNodeRelationshipAndPath() { - // Given - assertOnlyDeserializesValue(valueFactory.emptyNodeValue()); - assertOnlyDeserializesValue(valueFactory.filledNodeValue()); - assertOnlyDeserializesValue(valueFactory.emptyRelationshipValue()); - assertOnlyDeserializesValue(valueFactory.filledRelationshipValue()); - assertOnlyDeserializesValue(valueFactory.emptyPathValue()); - assertOnlyDeserializesValue(valueFactory.filledPathValue()); - } - - @Test - @SuppressWarnings("ExtractMethodRecommender") - void shouldGiveHelpfulErrorOnMalformedNodeStruct() throws Throwable { - // Given - var output = new ChunkAwareByteBufOutput(); - var buf = Unpooled.buffer(); - output.start(buf); - var packer = new PackStream.Packer(output); - - packer.packStructHeader(1, RecordMessage.SIGNATURE); - packer.packListHeader(1); - packer.packStructHeader(0, CommonValueUnpacker.NODE); - - output.stop(); - BoltProtocolUtil.writeMessageBoundary(buf); - - var channel = newEmbeddedChannel(); - var dispatcher = messageDispatcher(channel); - var memorizingDispatcher = ((MemorizingInboundMessageDispatcher) dispatcher); - var errorFuture = new CompletableFuture(); - memorizingDispatcher.enqueue(new ResponseHandler() { - @Override - public void onSuccess(Map metadata) { - errorFuture.complete(null); - } - - @Override - public void onFailure(Throwable error) { - errorFuture.completeExceptionally(error); - } - - @Override - public void onRecord(Value[] fields) { - // ignored - } - }); - channel.writeInbound(buf); - - // Expect - Throwable error = assertThrows(CompletionException.class, errorFuture::join); - error = assertInstanceOf(BoltClientException.class, error.getCause()); - assertTrue( - error.getMessage() - .startsWith( - "Invalid message received, serialized NODE structures should have 3 fields, received NODE structure has 0 fields.")); - } - - private void assertSerializesValue(Value value) { - assertSerializes(new RecordMessage(new Value[] {value})); - } - - private void assertSerializes(Message message) { - var channel = newEmbeddedChannel(new KnowledgeableMessageFormat(false)); - - var packed = pack(message, channel); - var unpackedMessage = unpack(packed, channel); - - assertEquals(message, unpackedMessage); - } - - private EmbeddedChannel newEmbeddedChannel() { - return newEmbeddedChannel(format); - } - - private EmbeddedChannel newEmbeddedChannel(MessageFormat format) { - var channel = new EmbeddedChannel(); - setMessageDispatcher(channel, new MemorizingInboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE)); - new ChannelPipelineBuilderImpl().build(format, channel.pipeline(), NoopLoggingProvider.INSTANCE, valueFactory); - return channel; - } - - private ByteBuf pack(Message message, EmbeddedChannel channel) { - assertTrue(channel.writeOutbound(message)); - - var packedMessages = - channel.outboundMessages().stream().map(msg -> (ByteBuf) msg).toArray(ByteBuf[]::new); - - return Unpooled.wrappedBuffer(packedMessages); - } - - private Message unpack(ByteBuf packed, EmbeddedChannel channel) { - channel.writeInbound(packed); - - var dispatcher = messageDispatcher(channel); - var memorizingDispatcher = ((MemorizingInboundMessageDispatcher) dispatcher); - - var unpackedMessages = memorizingDispatcher.messages(); - - assertEquals(1, unpackedMessages.size()); - return unpackedMessages.get(0); - } - - private void assertOnlyDeserializesValue(Value value) { - var message = new RecordMessage(new Value[] {value}); - var packed = knowledgeablePack(message); - - var channel = newEmbeddedChannel(); - var unpackedMessage = unpack(packed, channel); - - assertEquals(message, unpackedMessage); - } - - private ByteBuf knowledgeablePack(Message message) { - var channel = newEmbeddedChannel(new KnowledgeableMessageFormat(false)); - assertTrue(channel.writeOutbound(message)); - - var packedMessages = - channel.outboundMessages().stream().map(msg -> (ByteBuf) msg).toArray(ByteBuf[]::new); - - return Unpooled.wrappedBuffer(packedMessages); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/BeginMessageEncoderTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/BeginMessageEncoderTest.java deleted file mode 100644 index eef51422e3..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/BeginMessageEncoderTest.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.neo4j.driver.internal.bolt.api.AccessMode.READ; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage.RESET; - -import java.time.Duration; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.DatabaseNameUtil; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; - -class BeginMessageEncoderTest { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private final BeginMessageEncoder encoder = new BeginMessageEncoder(); - private final ValuePacker packer = mock(ValuePacker.class); - - @ParameterizedTest - @MethodSource("arguments") - void shouldEncodeBeginMessage(AccessMode mode, String impersonatedUser, String txType) throws Exception { - var bookmarks = Set.of("neo4j:bookmark:v1:tx42"); - - Map txMetadata = new HashMap<>(); - txMetadata.put("hello", valueFactory.value("world")); - txMetadata.put("answer", valueFactory.value(42)); - - var txTimeout = Duration.ofSeconds(1); - - var loggingProvider = new LoggingProvider() { - @Override - public System.Logger getLog(Class cls) { - return mock(System.Logger.class); - } - - @Override - public System.Logger getLog(String name) { - return mock(System.Logger.class); - } - }; - - encoder.encode( - new BeginMessage( - bookmarks, - txTimeout, - txMetadata, - mode, - DatabaseNameUtil.defaultDatabase(), - impersonatedUser, - txType, - null, - false, - loggingProvider, - valueFactory), - packer, - valueFactory); - - var order = inOrder(packer); - order.verify(packer).packStructHeader(1, BeginMessage.SIGNATURE); - - Map expectedMetadata = new HashMap<>(); - expectedMetadata.put( - "bookmarks", - valueFactory.value(bookmarks.stream().map(valueFactory::value).collect(Collectors.toSet()))); - expectedMetadata.put("tx_timeout", valueFactory.value(1000)); - expectedMetadata.put("tx_metadata", valueFactory.value(txMetadata)); - if (mode == READ) { - expectedMetadata.put("mode", valueFactory.value("r")); - } - if (impersonatedUser != null) { - expectedMetadata.put("imp_user", valueFactory.value(impersonatedUser)); - } - if (txType != null) { - expectedMetadata.put("tx_type", valueFactory.value(txType)); - } - - order.verify(packer).pack(expectedMetadata); - } - - private static Stream arguments() { - return Arrays.stream(AccessMode.values()) - .flatMap(accessMode -> - Stream.of(Arguments.of(accessMode, "user", "IMPLICIT"), Arguments.of(accessMode, null, null))); - } - - @Test - void shouldFailToEncodeWrongMessage() { - assertThrows(IllegalArgumentException.class, () -> encoder.encode(RESET, packer, valueFactory)); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/CommitMessageEncoderTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/CommitMessageEncoderTest.java deleted file mode 100644 index 7cac1d20a3..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/CommitMessageEncoderTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage.COMMIT; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage.DISCARD_ALL; - -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; - -class CommitMessageEncoderTest { - private final CommitMessageEncoder encoder = new CommitMessageEncoder(); - private final ValuePacker packer = mock(ValuePacker.class); - - @Test - void shouldEncodeCommitMessage() throws Exception { - encoder.encode(COMMIT, packer, mock(ValueFactory.class)); - - verify(packer).packStructHeader(0, CommitMessage.SIGNATURE); - } - - @Test - void shouldFailToEncodeWrongMessage() { - assertThrows( - IllegalArgumentException.class, () -> encoder.encode(DISCARD_ALL, packer, mock(ValueFactory.class))); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/DiscardAllMessageEncoderTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/DiscardAllMessageEncoderTest.java deleted file mode 100644 index 2a71b69b52..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/DiscardAllMessageEncoderTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardMessage; - -class DiscardAllMessageEncoderTest { - private final DiscardAllMessageEncoder encoder = new DiscardAllMessageEncoder(); - private final ValuePacker packer = mock(ValuePacker.class); - - @Test - void shouldEncodeDiscardAllMessage() throws Exception { - encoder.encode(DiscardAllMessage.DISCARD_ALL, packer, mock(ValueFactory.class)); - - verify(packer).packStructHeader(0, DiscardAllMessage.SIGNATURE); - } - - @Test - void shouldFailToEncodeWrongMessage() { - assertThrows( - IllegalArgumentException.class, - () -> encoder.encode( - new DiscardMessage(100, 200, mock(ValueFactory.class)), packer, mock(ValueFactory.class))); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/DiscardMessageEncoderTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/DiscardMessageEncoderTest.java deleted file mode 100644 index d8e90a4eed..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/DiscardMessageEncoderTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; - -import java.util.HashMap; -import java.util.Map; -import org.junit.jupiter.api.Test; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardMessage; - -class DiscardMessageEncoderTest { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private final DiscardMessageEncoder encoder = new DiscardMessageEncoder(); - private final ValuePacker packer = mock(ValuePacker.class); - - @Test - void shouldDiscardAllCorrectly() throws Throwable { - encoder.encode(new DiscardMessage(-1, -1, valueFactory), packer, valueFactory); - - Map meta = new HashMap<>(); - meta.put("n", valueFactory.value(-1)); - - var order = inOrder(packer); - order.verify(packer).packStructHeader(1, DiscardMessage.SIGNATURE); - order.verify(packer).pack(meta); - } - - @Test - void shouldEncodeDiscardMessage() throws Exception { - encoder.encode(new DiscardMessage(100, 200, valueFactory), packer, valueFactory); - - Map meta = new HashMap<>(); - meta.put("n", valueFactory.value(100)); - meta.put("qid", valueFactory.value(200)); - - var order = inOrder(packer); - order.verify(packer).packStructHeader(1, DiscardMessage.SIGNATURE); - order.verify(packer).pack(meta); - } - - @Test - void shouldAvoidQueryId() throws Throwable { - encoder.encode(new DiscardMessage(100, -1, valueFactory), packer, valueFactory); - - Map meta = new HashMap<>(); - meta.put("n", valueFactory.value(100)); - - var order = inOrder(packer); - order.verify(packer).packStructHeader(1, DiscardMessage.SIGNATURE); - order.verify(packer).pack(meta); - } - - @Test - void shouldFailToEncodeWrongMessage() { - assertThrows( - IllegalArgumentException.class, - () -> encoder.encode(DiscardAllMessage.DISCARD_ALL, packer, valueFactory)); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/GoodbyeMessageEncoderTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/GoodbyeMessageEncoderTest.java deleted file mode 100644 index b906f7dbac..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/GoodbyeMessageEncoderTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage.DISCARD_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage.GOODBYE; - -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage; - -class GoodbyeMessageEncoderTest { - private final GoodbyeMessageEncoder encoder = new GoodbyeMessageEncoder(); - private final ValuePacker packer = mock(ValuePacker.class); - - @Test - void shouldEncodeGoodbyeMessage() throws Exception { - encoder.encode(GOODBYE, packer, mock(ValueFactory.class)); - - verify(packer).packStructHeader(0, GoodbyeMessage.SIGNATURE); - } - - @Test - void shouldFailToEncodeWrongMessage() { - assertThrows( - IllegalArgumentException.class, () -> encoder.encode(DISCARD_ALL, packer, mock(ValueFactory.class))); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/HelloMessageEncoderTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/HelloMessageEncoderTest.java deleted file mode 100644 index 50e319a2ab..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/HelloMessageEncoderTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullAllMessage.PULL_ALL; - -import java.util.HashMap; -import java.util.Map; -import org.junit.jupiter.api.Test; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.BoltAgentUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; - -class HelloMessageEncoderTest { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private final HelloMessageEncoder encoder = new HelloMessageEncoder(); - private final ValuePacker packer = mock(ValuePacker.class); - - @Test - void shouldEncodeHelloMessage() throws Exception { - Map authToken = new HashMap<>(); - authToken.put("username", valueFactory.value("bob")); - authToken.put("password", valueFactory.value("secret")); - - encoder.encode( - new HelloMessage("MyDriver", BoltAgentUtil.VALUE, authToken, null, false, null, false, valueFactory), - packer, - valueFactory); - - var order = inOrder(packer); - order.verify(packer).packStructHeader(1, HelloMessage.SIGNATURE); - - Map expectedMetadata = new HashMap<>(authToken); - expectedMetadata.put("user_agent", valueFactory.value("MyDriver")); - expectedMetadata.put("bolt_agent", valueFactory.value(Map.of("product", BoltAgentUtil.VALUE.product()))); - order.verify(packer).pack(expectedMetadata); - } - - @Test - void shouldEncodeHelloMessageWithRoutingContext() throws Exception { - Map authToken = new HashMap<>(); - authToken.put("username", valueFactory.value("bob")); - authToken.put("password", valueFactory.value("secret")); - - Map routingContext = new HashMap<>(); - routingContext.put("policy", "eu-fast"); - - encoder.encode( - new HelloMessage( - "MyDriver", BoltAgentUtil.VALUE, authToken, routingContext, false, null, false, valueFactory), - packer, - valueFactory); - - var order = inOrder(packer); - order.verify(packer).packStructHeader(1, HelloMessage.SIGNATURE); - - Map expectedMetadata = new HashMap<>(authToken); - expectedMetadata.put("user_agent", valueFactory.value("MyDriver")); - expectedMetadata.put("bolt_agent", valueFactory.value(Map.of("product", BoltAgentUtil.VALUE.product()))); - expectedMetadata.put("routing", valueFactory.value(routingContext)); - order.verify(packer).pack(expectedMetadata); - } - - @Test - void shouldFailToEncodeWrongMessage() { - assertThrows(IllegalArgumentException.class, () -> encoder.encode(PULL_ALL, packer, valueFactory)); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/PullAllMessageEncoderTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/PullAllMessageEncoderTest.java deleted file mode 100644 index e81d255ebb..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/PullAllMessageEncoderTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullAllMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; - -class PullAllMessageEncoderTest { - private final PullAllMessageEncoder encoder = new PullAllMessageEncoder(); - private final ValuePacker packer = mock(ValuePacker.class); - - @Test - void shouldEncodePullAllMessage() throws Exception { - encoder.encode(PullAllMessage.PULL_ALL, packer, mock(ValueFactory.class)); - - verify(packer).packStructHeader(0, PullAllMessage.SIGNATURE); - } - - @Test - void shouldFailToEncodeWrongMessage() { - assertThrows( - IllegalArgumentException.class, - () -> encoder.encode( - new PullMessage(100, 200, mock(ValueFactory.class)), packer, mock(ValueFactory.class))); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/PullMessageEncoderTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/PullMessageEncoderTest.java deleted file mode 100644 index ab49f4fbc5..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/PullMessageEncoderTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; - -import java.util.HashMap; -import java.util.Map; -import org.junit.jupiter.api.Test; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullAllMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; - -class PullMessageEncoderTest { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private final PullMessageEncoder encoder = new PullMessageEncoder(); - private final ValuePacker packer = mock(ValuePacker.class); - - @Test - void shouldSendPullAllCorrectly() throws Throwable { - encoder.encode(new PullMessage(-1, -1, valueFactory), packer, valueFactory); - - Map meta = new HashMap<>(); - meta.put("n", valueFactory.value(-1)); - - var order = inOrder(packer); - order.verify(packer).packStructHeader(1, PullMessage.SIGNATURE); - order.verify(packer).pack(meta); - } - - @Test - void shouldEncodePullMessage() throws Exception { - encoder.encode(new PullMessage(100, 200, valueFactory), packer, valueFactory); - - Map meta = new HashMap<>(); - meta.put("n", valueFactory.value(100)); - meta.put("qid", valueFactory.value(200)); - - var order = inOrder(packer); - order.verify(packer).packStructHeader(1, PullMessage.SIGNATURE); - order.verify(packer).pack(meta); - } - - @Test - void shouldAvoidQueryId() throws Exception { - encoder.encode(new PullMessage(100, -1, valueFactory), packer, valueFactory); - - Map meta = new HashMap<>(); - meta.put("n", valueFactory.value(100)); - - var order = inOrder(packer); - order.verify(packer).packStructHeader(1, PullMessage.SIGNATURE); - order.verify(packer).pack(meta); - } - - @Test - void shouldFailToEncodeWrongMessage() { - assertThrows( - IllegalArgumentException.class, () -> encoder.encode(PullAllMessage.PULL_ALL, packer, valueFactory)); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/ResetMessageEncoderTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/ResetMessageEncoderTest.java deleted file mode 100644 index 2cebb74a38..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/ResetMessageEncoderTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -import java.util.Collections; -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage; - -class ResetMessageEncoderTest { - private final ResetMessageEncoder encoder = new ResetMessageEncoder(); - private final ValuePacker packer = mock(ValuePacker.class); - - @Test - void shouldEncodeResetMessage() throws Exception { - encoder.encode(ResetMessage.RESET, packer, mock(ValueFactory.class)); - - verify(packer).packStructHeader(0, ResetMessage.SIGNATURE); - } - - @Test - void shouldFailToEncodeWrongMessage() { - assertThrows( - IllegalArgumentException.class, - () -> encoder.encode( - RunWithMetadataMessage.unmanagedTxRunMessage("RETURN 2", Collections.emptyMap()), - packer, - mock(ValueFactory.class))); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/RollbackMessageEncoderTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/RollbackMessageEncoderTest.java deleted file mode 100644 index 1207e6d791..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/RollbackMessageEncoderTest.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage.RESET; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage.ROLLBACK; - -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; - -class RollbackMessageEncoderTest { - private final RollbackMessageEncoder encoder = new RollbackMessageEncoder(); - private final ValuePacker packer = mock(ValuePacker.class); - - @Test - void shouldEncodeRollbackMessage() throws Exception { - encoder.encode(ROLLBACK, packer, mock(ValueFactory.class)); - - verify(packer).packStructHeader(0, RollbackMessage.SIGNATURE); - } - - @Test - void shouldFailToEncodeWrongMessage() { - assertThrows(IllegalArgumentException.class, () -> encoder.encode(RESET, packer, mock(ValueFactory.class))); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/RouteMessageEncoderTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/RouteMessageEncoderTest.java deleted file mode 100644 index 1ddc407927..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/RouteMessageEncoderTest.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static java.util.Collections.emptyList; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; - -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.NullSource; -import org.junit.jupiter.params.provider.ValueSource; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RouteMessage; - -class RouteMessageEncoderTest { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private final ValuePacker packer = mock(ValuePacker.class); - private final RouteMessageEncoder encoder = new RouteMessageEncoder(); - - @ParameterizedTest - @ValueSource(strings = {"neo4j"}) - @NullSource - void shouldEncodeRouteMessage(String databaseName) throws IOException { - var routingContext = getRoutingContext(); - - encoder.encode( - new RouteMessage(getRoutingContext(), Collections.emptySet(), databaseName, null), - packer, - valueFactory); - - var inOrder = inOrder(packer); - - inOrder.verify(packer).packStructHeader(3, (byte) 0x66); - inOrder.verify(packer).pack(routingContext); - inOrder.verify(packer).pack(valueFactory.value(emptyList())); - inOrder.verify(packer).pack(databaseName); - } - - @ParameterizedTest - @ValueSource(strings = {"neo4j"}) - @NullSource - void shouldEncodeRouteMessageWithBookmark(String databaseName) throws IOException { - var routingContext = getRoutingContext(); - var bookmark = "somebookmark"; - - encoder.encode( - new RouteMessage(getRoutingContext(), Collections.singleton(bookmark), databaseName, null), - packer, - valueFactory); - - var inOrder = inOrder(packer); - - inOrder.verify(packer).packStructHeader(3, (byte) 0x66); - inOrder.verify(packer).pack(routingContext); - inOrder.verify(packer).pack(valueFactory.value(Collections.singleton(valueFactory.value(bookmark)))); - inOrder.verify(packer).pack(databaseName); - } - - @Test - void shouldThrowIllegalArgumentIfMessageIsNotRouteMessage() { - var message = mock(Message.class); - - assertThrows(IllegalArgumentException.class, () -> encoder.encode(message, packer, valueFactory)); - } - - private Map getRoutingContext() { - Map routingContext = new HashMap<>(); - routingContext.put("ip", valueFactory.value("127.0.0.1")); - return routingContext; - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/RunWithMetadataMessageEncoderTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/RunWithMetadataMessageEncoderTest.java deleted file mode 100644 index 0c6d8b5c68..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/RunWithMetadataMessageEncoderTest.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static java.util.Collections.singletonMap; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.neo4j.driver.internal.bolt.api.AccessMode.READ; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage.DISCARD_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; - -import java.time.Duration; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage; - -class RunWithMetadataMessageEncoderTest { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private final RunWithMetadataMessageEncoder encoder = new RunWithMetadataMessageEncoder(); - private final ValuePacker packer = mock(ValuePacker.class); - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldEncodeRunWithMetadataMessage(AccessMode mode) throws Exception { - var params = singletonMap("answer", valueFactory.value(42)); - - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx999"); - - Map txMetadata = new HashMap<>(); - txMetadata.put("key1", valueFactory.value("value1")); - txMetadata.put("key2", valueFactory.value(List.of(1, 2, 3, 4, 5))); - txMetadata.put("key3", valueFactory.value(true)); - - var txTimeout = Duration.ofMillis(42); - - encoder.encode( - autoCommitTxRunMessage( - "RETURN $answer", - params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - new LoggingProvider() { - @Override - public System.Logger getLog(Class cls) { - return mock(System.Logger.class); - } - - @Override - public System.Logger getLog(String name) { - return mock(System.Logger.class); - } - }, - valueFactory), - packer, - valueFactory); - - var order = inOrder(packer); - order.verify(packer).packStructHeader(3, RunWithMetadataMessage.SIGNATURE); - order.verify(packer).pack("RETURN $answer"); - order.verify(packer).pack(params); - - Map expectedMetadata = new HashMap<>(); - expectedMetadata.put( - "bookmarks", - valueFactory.value(bookmarks.stream().map(valueFactory::value).collect(Collectors.toSet()))); - expectedMetadata.put("tx_timeout", valueFactory.value(42)); - expectedMetadata.put("tx_metadata", valueFactory.value(txMetadata)); - if (mode == READ) { - expectedMetadata.put("mode", valueFactory.value("r")); - } - - order.verify(packer).pack(expectedMetadata); - } - - @Test - void shouldFailToEncodeWrongMessage() { - assertThrows(IllegalArgumentException.class, () -> encoder.encode(DISCARD_ALL, packer, valueFactory)); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/TelemetryMessageEncoderTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/TelemetryMessageEncoderTest.java deleted file mode 100644 index 7971dd029f..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/encode/TelemetryMessageEncoderTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -import java.util.Collections; -import java.util.stream.Stream; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.TelemetryMessage; - -class TelemetryMessageEncoderTest { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private final TelemetryMessageEncoder encoder = new TelemetryMessageEncoder(); - private final ValuePacker packer = mock(ValuePacker.class); - - @ParameterizedTest - @MethodSource("validApis") - void shouldEncodeTelemetryMessage(int api) throws Exception { - encoder.encode(new TelemetryMessage(api), packer, valueFactory); - - verify(packer).packStructHeader(1, TelemetryMessage.SIGNATURE); - verify(packer).pack(valueFactory.value(api)); - } - - @Test - void shouldFailToEncodeWrongMessage() { - Assertions.assertThrows( - IllegalArgumentException.class, - () -> encoder.encode( - RunWithMetadataMessage.unmanagedTxRunMessage("RETURN 2", Collections.emptyMap()), - packer, - valueFactory)); - } - - private static Stream validApis() { - return Stream.of(TelemetryApi.values()).map(TelemetryApi::getValue); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/HelloMessageTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/HelloMessageTest.java deleted file mode 100644 index b448e2b015..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/HelloMessageTest.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import org.junit.jupiter.api.Test; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.BoltAgent; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.BoltAgentUtil; - -class HelloMessageTest { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - - @Test - void shouldHaveCorrectMetadata() { - Map authToken = new HashMap<>(); - authToken.put("user", valueFactory.value("Alice")); - authToken.put("credentials", valueFactory.value("SecretPassword")); - - var message = new HelloMessage( - "MyDriver/1.0.2", - BoltAgentUtil.VALUE, - authToken, - Collections.emptyMap(), - false, - null, - false, - valueFactory); - - Map expectedMetadata = new HashMap<>(authToken); - expectedMetadata.put("user_agent", valueFactory.value("MyDriver/1.0.2")); - expectedMetadata.put("bolt_agent", valueFactory.value(Map.of("product", BoltAgentUtil.VALUE.product()))); - expectedMetadata.put("routing", valueFactory.value(Collections.emptyMap())); - assertEquals(expectedMetadata, message.metadata()); - } - - @Test - void shouldHaveCorrectRoutingContext() { - Map authToken = new HashMap<>(); - authToken.put("user", valueFactory.value("Alice")); - authToken.put("credentials", valueFactory.value("SecretPassword")); - - Map routingContext = new HashMap<>(); - routingContext.put("region", "China"); - routingContext.put("speed", "Slow"); - - var message = new HelloMessage( - "MyDriver/1.0.2", BoltAgentUtil.VALUE, authToken, routingContext, false, null, false, valueFactory); - - Map expectedMetadata = new HashMap<>(authToken); - expectedMetadata.put("user_agent", valueFactory.value("MyDriver/1.0.2")); - expectedMetadata.put("bolt_agent", valueFactory.value(Map.of("product", BoltAgentUtil.VALUE.product()))); - expectedMetadata.put("routing", valueFactory.value(routingContext)); - assertEquals(expectedMetadata, message.metadata()); - } - - @Test - void shouldNotExposeCredentialsInToString() { - Map authToken = new HashMap<>(); - authToken.put("principal", valueFactory.value("Alice")); - authToken.put("credentials", valueFactory.value("SecretPassword")); - - var message = new HelloMessage( - "MyDriver/1.0.2", - BoltAgentUtil.VALUE, - authToken, - Collections.emptyMap(), - false, - null, - false, - valueFactory); - - assertFalse(message.toString().contains("SecretPassword")); - } - - @Test - void shouldAcceptNullBoltAgent() { - var authToken = new HashMap(); - authToken.put("user", valueFactory.value("Alice")); - authToken.put("credentials", valueFactory.value("SecretPassword")); - - var message = new HelloMessage( - "MyDriver/1.0.2", null, authToken, Collections.emptyMap(), false, null, false, valueFactory); - - var expectedMetadata = new HashMap<>(authToken); - expectedMetadata.put("user_agent", valueFactory.value("MyDriver/1.0.2")); - expectedMetadata.put("routing", valueFactory.value(Collections.emptyMap())); - assertEquals(expectedMetadata, message.metadata()); - } - - @Test - void shouldAcceptDetailedBoltAgent() { - var authToken = new HashMap(); - authToken.put("user", valueFactory.value("Alice")); - authToken.put("credentials", valueFactory.value("SecretPassword")); - var boltAgent = new BoltAgent("1", "2", "3", "4"); - - var message = new HelloMessage( - "MyDriver/1.0.2", boltAgent, authToken, Collections.emptyMap(), false, null, false, valueFactory); - - var expectedMetadata = new HashMap<>(authToken); - expectedMetadata.put("user_agent", valueFactory.value("MyDriver/1.0.2")); - expectedMetadata.put( - "bolt_agent", - valueFactory.value(Map.of( - "product", - boltAgent.product(), - "platform", - boltAgent.platform(), - "language", - boltAgent.language(), - "language_details", - boltAgent.languageDetails()))); - expectedMetadata.put("routing", valueFactory.value(Collections.emptyMap())); - assertEquals(expectedMetadata, message.metadata()); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/TransactionMetadataBuilderTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/TransactionMetadataBuilderTest.java deleted file mode 100644 index b195e8e0c4..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/request/TransactionMetadataBuilderTest.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request; - -import static java.util.Arrays.asList; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.mock; -import static org.neo4j.driver.internal.bolt.api.AccessMode.READ; -import static org.neo4j.driver.internal.bolt.api.AccessMode.WRITE; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.TransactionMetadataBuilder.buildMetadata; - -import java.time.Duration; -import java.time.LocalDateTime; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.junit.jupiter.params.provider.ValueSource; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.NotificationClassification; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.NotificationSeverity; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; - -public class TransactionMetadataBuilderTest { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldHaveCorrectMetadata(AccessMode mode) { - var bookmarks = new HashSet<>(asList("neo4j:bookmark:v1:tx11", "neo4j:bookmark:v1:tx52")); - - Map txMetadata = new HashMap<>(); - txMetadata.put("foo", valueFactory.value("bar")); - txMetadata.put("baz", valueFactory.value(111)); - txMetadata.put("time", valueFactory.value(LocalDateTime.now())); - - var txTimeout = Duration.ofSeconds(7); - - var metadata = buildMetadata( - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - - Map expectedMetadata = new HashMap<>(); - expectedMetadata.put( - "bookmarks", - valueFactory.value(bookmarks.stream().map(valueFactory::value).collect(Collectors.toSet()))); - expectedMetadata.put("tx_timeout", valueFactory.value(7000)); - expectedMetadata.put("tx_metadata", valueFactory.value(txMetadata)); - if (mode == READ) { - expectedMetadata.put("mode", valueFactory.value("r")); - } - - assertEquals(expectedMetadata, metadata); - } - - @ParameterizedTest - @ValueSource(strings = {"", "foo", "data"}) - void shouldHaveCorrectMetadataForDatabaseName(String databaseName) { - var bookmarks = new HashSet<>(asList("neo4j:bookmark:v1:tx11", "neo4j:bookmark:v1:tx52")); - - Map txMetadata = new HashMap<>(); - txMetadata.put("foo", valueFactory.value("bar")); - txMetadata.put("baz", valueFactory.value(111)); - txMetadata.put("time", valueFactory.value(LocalDateTime.now())); - - var txTimeout = Duration.ofSeconds(7); - - var metadata = buildMetadata( - txTimeout, - txMetadata, - database(databaseName), - WRITE, - bookmarks, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - - Map expectedMetadata = new HashMap<>(); - expectedMetadata.put( - "bookmarks", - valueFactory.value(bookmarks.stream().map(valueFactory::value).collect(Collectors.toSet()))); - expectedMetadata.put("tx_timeout", valueFactory.value(7000)); - expectedMetadata.put("tx_metadata", valueFactory.value(txMetadata)); - expectedMetadata.put("db", valueFactory.value(databaseName)); - - assertEquals(expectedMetadata, metadata); - } - - @Test - void shouldNotHaveMetadataForDatabaseNameWhenIsNull() { - var metadata = buildMetadata( - null, - null, - defaultDatabase(), - WRITE, - Collections.emptySet(), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertTrue(metadata.isEmpty()); - } - - @SuppressWarnings("OptionalGetWithoutIsPresent") - @Test - void shouldIncludeNotificationConfig() { - var metadata = buildMetadata( - null, - null, - defaultDatabase(), - WRITE, - Collections.emptySet(), - null, - null, - new NotificationConfig( - NotificationSeverity.WARNING, - Set.of(NotificationClassification.valueOf("UNSUPPORTED").get())), - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - - var expectedMetadata = new HashMap(); - expectedMetadata.put("notifications_minimum_severity", valueFactory.value("WARNING")); - expectedMetadata.put("notifications_disabled_classifications", valueFactory.value(Set.of("UNSUPPORTED"))); - assertEquals(expectedMetadata, metadata); - } - - @ParameterizedTest - @ValueSource(longs = {1, 1_000_001, 100_500_000, 100_700_000, 1_000_000_001}) - void shouldRoundUpFractionalTimeoutAndLog(long nanosValue) { - // given - var logging = mock(LoggingProvider.class); - var logger = mock(System.Logger.class); - given(logging.getLog(TransactionMetadataBuilder.class)).willReturn(logger); - - // when - var metadata = buildMetadata( - Duration.ofNanos(nanosValue), - null, - defaultDatabase(), - WRITE, - Collections.emptySet(), - null, - null, - null, - false, - logging, - valueFactory); - - // then - var expectedMetadata = new HashMap(); - var expectedMillis = nanosValue / 1_000_000 + 1; - expectedMetadata.put("tx_timeout", valueFactory.value(expectedMillis)); - assertEquals(expectedMetadata, metadata); - then(logging).should().getLog(TransactionMetadataBuilder.class); - then(logger) - .should() - .log( - System.Logger.Level.INFO, - "The transaction timeout has been rounded up to next millisecond value since the config had a fractional millisecond value"); - } - - @Test - void shouldNotLogWhenRoundingDoesNotHappen() { - // given - var logging = mock(LoggingProvider.class); - var logger = mock(System.Logger.class); - given(logging.getLog(TransactionMetadataBuilder.class)).willReturn(logger); - var timeout = 1000; - - // when - var metadata = buildMetadata( - Duration.ofMillis(timeout), - null, - defaultDatabase(), - WRITE, - Collections.emptySet(), - null, - null, - null, - false, - logging, - valueFactory); - - // then - var expectedMetadata = new HashMap(); - expectedMetadata.put("tx_timeout", valueFactory.value(timeout)); - assertEquals(expectedMetadata, metadata); - then(logging).shouldHaveNoInteractions(); - then(logger).shouldHaveNoInteractions(); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/response/RecordMessageTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/response/RecordMessageTest.java deleted file mode 100644 index 2f96a83e50..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/response/RecordMessageTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.util.Collections; -import java.util.stream.Stream; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; - -class RecordMessageTest { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - - @ParameterizedTest - @MethodSource("equalsArgs") - void shouldEquals(RecordMessage message1, Object message2, boolean equals) { - assertEquals(equals, message1.equals(message2)); - } - - static Stream equalsArgs() { - var message = new RecordMessage(new Value[] {valueFactory.value(1), valueFactory.value("1")}); - return Stream.of( - Arguments.of( - message, new RecordMessage(new Value[] {valueFactory.value(1), valueFactory.value("1")}), true), - Arguments.of( - message, - new RecordMessage(new Value[] {valueFactory.value(2), valueFactory.value("2")}), - false), - Arguments.of(message, new SuccessMessage(Collections.emptyMap()), false), - Arguments.of(message, message, true), - Arguments.of(message, null, false)); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v3/BoltProtocolV3Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v3/BoltProtocolV3Test.java deleted file mode 100644 index efdd345cd7..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v3/BoltProtocolV3Test.java +++ /dev/null @@ -1,810 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3; - -import static java.time.Duration.ofSeconds; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.api.AccessMode.WRITE; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import io.netty.channel.embedded.EmbeddedChannel; -import java.time.Clock; -import java.time.Duration; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.TimeUnit; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.mockito.stubbing.Answer; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.exception.BoltClientException; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.RouteSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.GqlErrorUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.BeginTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.CommitTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.PullResponseHandlerImpl; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RollbackTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RunResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.PullMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullAllMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public class BoltProtocolV3Test { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private static final String query = "RETURN $x"; - private static final Map query_params = singletonMap("x", value(42)); - private static final long UNLIMITED_FETCH_SIZE = -1; - private static final Duration txTimeout = ofSeconds(12); - private static final Map txMetadata = singletonMap("x", value(42)); - - protected final BoltProtocol protocol = createProtocol(); - private final EmbeddedChannel channel = new EmbeddedChannel(); - private final InboundMessageDispatcher messageDispatcher = - new InboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE); - - @BeforeEach - void beforeEach() { - ChannelAttributes.setMessageDispatcher(channel, messageDispatcher); - } - - @AfterEach - void afterEach() { - channel.finishAndReleaseAll(); - } - - @SuppressWarnings("SameReturnValue") - protected BoltProtocol createProtocol() { - return BoltProtocolV3.INSTANCE; - } - - protected Class expectedMessageFormatType() { - return MessageFormatV3.class; - } - - @Test - void shouldCreateMessageFormat() { - assertInstanceOf(expectedMessageFormatType(), protocol.createMessageFormat()); - } - - @Test - void shouldInitializeChannel() { - var clock = mock(Clock.class); - var time = 1L; - when(clock.millis()).thenReturn(time); - - var latestAuthMillisFuture = new CompletableFuture(); - - var future = protocol.initializeChannel( - channel, - "MyDriver/0.0.1", - null, - emptyMap(), - RoutingContext.EMPTY, - null, - clock, - latestAuthMillisFuture, - valueFactory) - .toCompletableFuture(); - - assertEquals(1, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertEquals(1, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - var metadata = Map.of( - "server", value("Neo4j/3.5.0"), - "connection_id", value("bolt-42")); - - messageDispatcher.handleSuccessMessage(metadata); - - assertTrue(future.isDone()); - assertEquals(channel, future.join()); - verify(clock).millis(); - assertTrue(latestAuthMillisFuture.isDone()); - assertEquals(time, latestAuthMillisFuture.join()); - } - - @Test - void shouldFailToInitializeChannelWhenErrorIsReceived() { - var future = protocol.initializeChannel( - channel, - "MyDriver/2.2.1", - null, - Collections.emptyMap(), - RoutingContext.EMPTY, - null, - mock(Clock.class), - new CompletableFuture<>(), - valueFactory) - .toCompletableFuture(); - - assertEquals(1, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertEquals(1, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - messageDispatcher.handleFailureMessage( - GqlErrorUtil.gqlError("Neo.TransientError.General.DatabaseUnavailable", "Error!")); - - assertTrue(future.isDone()); - assertTrue(future.isCompletedExceptionally()); - } - - @Test - void shouldSendRoute() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - given(connection.write(any(), any())) - .willAnswer((Answer>) invocation -> { - var handler = (RunResponseHandler) invocation.getArgument(1); - handler.onSuccess(Map.of("fields", value(List.of("ttl", "servers")))); - return CompletableFuture.completedStage(null); - }) - .willAnswer((Answer>) invocation -> { - var handler = (PullResponseHandlerImpl) invocation.getArgument(1); - handler.onRecord(new Value[] { - value(1000), - value(List.of( - value(Map.of( - "role", - value("ROUTE"), - "addresses", - value(List.of(value("192.168.0.1:7867"))))), - value(Map.of( - "role", - value("WRITE"), - "addresses", - value(List.of(value("192.168.0.1:7867"))))), - value(Map.of( - "role", - value("READ"), - "addresses", - value(List.of(value("192.168.0.1:7867"))))))) - }); - handler.onSuccess(emptyMap()); - return CompletableFuture.completedStage(null); - }); - var routeFuture = new CompletableFuture(); - var handler = new MessageHandler() { - @Override - public void onError(Throwable throwable) { - routeFuture.completeExceptionally(throwable); - } - - @Override - public void onSummary(RouteSummary summary) { - routeFuture.complete(summary); - } - }; - - protocol.route( - connection, - Collections.emptyMap(), - Collections.emptySet(), - "neo4j", - null, - handler, - mock(Clock.class), - NoopLoggingProvider.INSTANCE, - valueFactory) - .toCompletableFuture() - .join(); - - var summary = routeFuture.join(); - assertEquals(summary.clusterComposition().expirationTimestamp(), TimeUnit.SECONDS.toMillis(1000)); - assertEquals(summary.clusterComposition().routers().size(), 1); - assertEquals(summary.clusterComposition().writers().size(), 1); - assertEquals(summary.clusterComposition().readers().size(), 1); - } - - @Test - void shouldBeginTransactionWithoutBookmark() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarks() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx100"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - WRITE, - null, - bookmarks, - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - null, - Collections.emptyMap(), - defaultDatabase(), - WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - WRITE, - null, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - txTimeout, - txMetadata, - defaultDatabase(), - WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarksAndConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx4242"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - WRITE, - null, - bookmarks, - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - txTimeout, - txMetadata, - defaultDatabase(), - WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldCommitTransaction() { - var bookmarkString = "neo4j:bookmark:v1:tx4242"; - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var commitHandler = (CommitTxResponseHandler) invocation.getArgument(1); - commitHandler.onSuccess(Map.of("bookmark", value(bookmarkString))); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.commitTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(CommitMessage.COMMIT), any(CommitTxResponseHandler.class)); - then(handler).should().onSummary(bookmarkString); - } - - @Test - void shouldRollbackTransaction() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var rollbackHandler = (RollbackTxResponseHandler) invocation.getArgument(1); - rollbackHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.rollbackTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(RollbackMessage.ROLLBACK), any(RollbackTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx65"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse(Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx163"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInUnmanagedTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(false, null, Collections.emptyMap(), mode); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForSuccessRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(true); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForFailureRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(false); - } - - @Test - void databaseNameInBeginTransaction() { - testDatabaseNameSupport(false); - } - - @Test - void databaseNameForAutoCommitTransactions() { - testDatabaseNameSupport(true); - } - - @Test - void shouldReturnFailedStageWithNoConnectionInteractionsOnTelemetry() { - var connection = mock(Connection.class); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var future = protocol.telemetry(connection, 1, handler).toCompletableFuture(); - - assertTrue(future.isCompletedExceptionally()); - then(connection).shouldHaveNoInteractions(); - } - - protected void testDatabaseNameSupport(boolean autoCommitTx) { - BoltClientException e; - if (autoCommitTx) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var future = protocol.runAuto( - connection, - database("foo"), - WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory) - .toCompletableFuture(); - e = (BoltClientException) - assertThrows(CompletionException.class, future::join).getCause(); - } else { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var future = protocol.beginTransaction( - connection, - database("foo"), - WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory) - .toCompletableFuture(); - e = (BoltClientException) - assertThrows(CompletionException.class, future::join).getCause(); - } - - assertTrue(e.getMessage().startsWith("Database name parameter for selecting database is not supported")); - } - - protected void testRunInUnmanagedTransactionAndWaitForRunResponse(boolean success) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - if (success) { - runHandler.onSuccess(emptyMap()); - } else { - runHandler.onFailure(error); - } - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - if (success) { - then(handler).should().onSummary(any()); - } else { - then(handler).should().onError(error); - } - } - - protected void testRunAndWaitForRunResponse( - boolean autoCommitTx, Duration txTimeout, Map txMetadata, AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var initialBookmarks = Collections.singleton("neo4j:bookmark:v1:tx987"); - - if (autoCommitTx) { - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - initialBookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - initialBookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - protected void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, Duration txTimeout, Map txMetadata, AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedRunStage = CompletableFuture.completedStage(null); - var expectedPullStage = CompletableFuture.completedStage(null); - var newBookmarkValue = "neo4j:bookmark:v1:tx98765"; - given(connection.write(any(), any())) - .willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedRunStage; - }) - .willAnswer((Answer>) invocation -> { - var pullHandler = (PullResponseHandlerImpl) invocation.getArgument(1); - pullHandler.onSuccess(Map.of("has_more", value(false), "bookmark", value(newBookmarkValue))); - return expectedPullStage; - }); - @SuppressWarnings("unchecked") - var runHandler = (MessageHandler) mock(MessageHandler.class); - var pullHandler = mock(PullMessageHandler.class); - - var runStage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - runHandler, - NoopLoggingProvider.INSTANCE, - valueFactory); - var pullStage = protocol.pull(connection, 0, UNLIMITED_FETCH_SIZE, pullHandler, valueFactory); - - assertEquals(expectedRunStage, runStage); - assertEquals(expectedPullStage, pullStage); - var runMessage = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(runMessage), any(RunResponseHandler.class)); - then(connection).should().write(eq(PullAllMessage.PULL_ALL), any(PullResponseHandlerImpl.class)); - then(runHandler).should().onSummary(any()); - then(pullHandler) - .should() - .onSummary(new PullResponseHandlerImpl.PullSummaryImpl( - false, Map.of("has_more", value(false), "bookmark", value(newBookmarkValue)))); - } - - protected void testFailedRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, Duration txTimeout, Map txMetadata, AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onFailure(error); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onError(error); - } - - private static Value value(Object value) { - return valueFactory.value(value); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v3/MessageFormatV3Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v3/MessageFormatV3Test.java deleted file mode 100644 index 9c61d1f466..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v3/MessageFormatV3Test.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3; - -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.mockito.Mockito.mock; - -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonMessageReader; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -/** - * The MessageFormat under tests is the one provided by the {@link BoltProtocolV3} and not an specific class implementation. - *

- * It's done on this way to make easy to replace the implementation and still getting the same behaviour. - */ -class MessageFormatV3Test { - private static final MessageFormat messageFormat = BoltProtocolV3.INSTANCE.createMessageFormat(); - - @Test - void shouldCreateCorrectWriter() { - var writer = messageFormat.newWriter(mock(PackOutput.class), mock(ValueFactory.class)); - - assertInstanceOf(MessageWriterV3.class, writer); - } - - @Test - void shouldCreateCorrectReader() { - var reader = messageFormat.newReader(mock(PackInput.class), mock(ValueFactory.class)); - - assertInstanceOf(CommonMessageReader.class, reader); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v3/MessageReaderV3Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v3/MessageReaderV3Test.java deleted file mode 100644 index 05983f756a..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v3/MessageReaderV3Test.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3; - -import static java.util.Arrays.asList; -import static java.util.Calendar.APRIL; -import static java.util.Calendar.AUGUST; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.HashMap; -import java.util.List; -import java.util.stream.Stream; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.FailureMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.IgnoredMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.RecordMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.SuccessMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.AbstractMessageReaderTestBase; - -/** - * The MessageReader under tests is the one provided by the {@link BoltProtocolV3} and not an specific class implementation. - *

- * It's done on this way to make easy to replace the implementation and still getting the same behaviour. - */ -public class MessageReaderV3Test extends AbstractMessageReaderTestBase { - - @Override - protected Stream supportedMessages() { - return Stream.of( - // V2 Record types - record(valueFactory.point(42, 120.65, -99.2)), - record(valueFactory.point(42, 85.391, 98.8, 11.1)), - record(valueFactory.value(LocalDate.of(2012, AUGUST, 3))), - record(valueFactory.value(OffsetTime.of(23, 59, 59, 999, ZoneOffset.MAX))), - record(valueFactory.value(LocalTime.of(12, 25))), - record(valueFactory.value(LocalDateTime.of(1999, APRIL, 3, 19, 5, 5, 100_200_300))), - record(valueFactory.value( - ZonedDateTime.of(1823, 1, 12, 23, 59, 59, 999_999_999, ZoneOffset.ofHoursMinutes(-7, -15)))), - record(valueFactory.value( - ZonedDateTime.of(1823, 1, 12, 23, 59, 59, 999_999_999, ZoneId.of("Europe/Stockholm")))), - record(valueFactory.isoDuration( - Long.MAX_VALUE - 1, Integer.MAX_VALUE - 1, Short.MAX_VALUE - 1, Byte.MAX_VALUE - 1)), - record(valueFactory.isoDuration(17, 22, 99, 15)), - - // Bolt previous versions valid messages - new FailureMessage("Hello", "World!"), - IgnoredMessage.IGNORED, - new SuccessMessage(new HashMap<>()), - record(valueFactory.value(1337L)), - record(valueFactory.value(List.of("cat", valueFactory.value(null), "dog", valueFactory.value(null)))), - record(valueFactory.value(List.of("k", valueFactory.value(12), "a", valueFactory.value("banana")))), - record(valueFactory.value(asList( - valueFactory.value("k"), - valueFactory.value(12), - valueFactory.value("a"), - valueFactory.value("banana")))), - - // V3 Record Types - record(valueFactory.emptyNodeValue()), - record(valueFactory.filledNodeValue()), - record(valueFactory.emptyRelationshipValue()), - record(valueFactory.filledRelationshipValue()), - record(valueFactory.filledPathValue()), - record(valueFactory.emptyPathValue())); - } - - @Override - protected Stream unsupportedMessages() { - return Stream.of(DiscardAllMessage.DISCARD_ALL); - } - - @Override - protected MessageFormat.Reader newReader(PackInput input) { - return BoltProtocolV3.INSTANCE.createMessageFormat().newReader(input, valueFactory); - } - - private Message record(Value value) { - return new RecordMessage(new Value[] {value}); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v3/MessageWriterV3Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v3/MessageWriterV3Test.java deleted file mode 100644 index 89de1b1037..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v3/MessageWriterV3Test.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3; - -import static java.time.Duration.ofSeconds; -import static java.util.Calendar.DECEMBER; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.neo4j.driver.internal.bolt.api.AccessMode.READ; -import static org.neo4j.driver.internal.bolt.api.AccessMode.WRITE; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage.COMMIT; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage.DISCARD_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage.GOODBYE; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullAllMessage.PULL_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage.RESET; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage.ROLLBACK; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.Collections; -import java.util.Map; -import java.util.stream.Stream; -import org.neo4j.driver.internal.bolt.basicimpl.impl.BoltAgentUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.AbstractMessageWriterTestBase; - -/** - * The MessageWriter under tests is the one provided by the {@link BoltProtocolV3} and not an specific class - * implementation. - *

- * It's done on this way to make easy to replace the implementation and still getting the same behaviour. - */ -class MessageWriterV3Test extends AbstractMessageWriterTestBase { - @Override - protected MessageFormat.Writer newWriter(PackOutput output) { - return BoltProtocolV3.INSTANCE.createMessageFormat().newWriter(output, valueFactory); - } - - @Override - protected Stream supportedMessages() { - return Stream.of( - // Bolt V2 Data Types - unmanagedTxRunMessage("RETURN $point", singletonMap("point", valueFactory.point(42, 12.99, -180.0))), - unmanagedTxRunMessage( - "RETURN $point", singletonMap("point", valueFactory.point(42, 0.51, 2.99, 100.123))), - unmanagedTxRunMessage( - "RETURN $date", singletonMap("date", valueFactory.value(LocalDate.ofEpochDay(2147483650L)))), - unmanagedTxRunMessage( - "RETURN $time", - singletonMap("time", valueFactory.value(OffsetTime.of(4, 16, 20, 999, ZoneOffset.MIN)))), - unmanagedTxRunMessage( - "RETURN $time", singletonMap("time", valueFactory.value(LocalTime.of(12, 9, 18, 999_888)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", valueFactory.value(LocalDateTime.of(2049, DECEMBER, 12, 17, 25, 49, 199)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value(ZonedDateTime.of( - 2000, 1, 10, 12, 2, 49, 300, ZoneOffset.ofHoursMinutes(9, 30))))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value( - ZonedDateTime.of(2000, 1, 10, 12, 2, 49, 300, ZoneId.of("Europe/Stockholm"))))), - - // Bolt V3 messages - new HelloMessage( - "MyDriver/1.2.3", - BoltAgentUtil.VALUE, - Map.of( - "scheme", - valueFactory.value("basic"), - "principal", - valueFactory.value("neo4j"), - "credentials", - valueFactory.value("neo4j")), - Collections.emptyMap(), - false, - null, - false, - valueFactory), - GOODBYE, - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - READ, - defaultDatabase(), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - WRITE, - defaultDatabase(), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - COMMIT, - ROLLBACK, - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - defaultDatabase(), - READ, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - defaultDatabase(), - WRITE, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN 1", Collections.emptyMap()), - PULL_ALL, - DISCARD_ALL, - RESET, - - // Bolt V3 messages with struct values - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - defaultDatabase(), - READ, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - defaultDatabase(), - WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN $x", singletonMap("x", valueFactory.point(42, 1, 2, 3)))); - } - - @Override - protected Stream unsupportedMessages() { - return Stream.empty(); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v4/BoltProtocolV4Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v4/BoltProtocolV4Test.java deleted file mode 100644 index 78d9d97780..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v4/BoltProtocolV4Test.java +++ /dev/null @@ -1,883 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v4; - -import static java.time.Duration.ofSeconds; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import io.netty.channel.embedded.EmbeddedChannel; -import java.time.Clock; -import java.time.Duration; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.TimeUnit; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.mockito.stubbing.Answer; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.RouteSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.GqlErrorUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.BeginTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.CommitTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.PullResponseHandlerImpl; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RollbackTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RunResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.PullMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public final class BoltProtocolV4Test { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private static final String query = "RETURN $x"; - private static final Map query_params = singletonMap("x", value(42)); - private static final long UNLIMITED_FETCH_SIZE = -1; - private static final Duration txTimeout = ofSeconds(12); - private static final Map txMetadata = singletonMap("x", value(42)); - - private final BoltProtocol protocol = createProtocol(); - private final EmbeddedChannel channel = new EmbeddedChannel(); - private final InboundMessageDispatcher messageDispatcher = - new InboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE); - - @BeforeEach - void beforeEach() { - ChannelAttributes.setMessageDispatcher(channel, messageDispatcher); - } - - @AfterEach - void afterEach() { - channel.finishAndReleaseAll(); - } - - @Test - void shouldCreateMessageFormat() { - assertInstanceOf(expectedMessageFormatType(), protocol.createMessageFormat()); - } - - @Test - void shouldInitializeChannel() { - var clock = mock(Clock.class); - var time = 1L; - when(clock.millis()).thenReturn(time); - - var latestAuthMillisFuture = new CompletableFuture(); - - var future = protocol.initializeChannel( - channel, - "MyDriver/0.0.1", - null, - Collections.emptyMap(), - RoutingContext.EMPTY, - null, - clock, - latestAuthMillisFuture, - valueFactory) - .toCompletableFuture(); - - assertEquals(1, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertEquals(1, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - var metadata = Map.of( - "server", value("Neo4j/3.5.0"), - "connection_id", value("bolt-42")); - - messageDispatcher.handleSuccessMessage(metadata); - - assertTrue(future.isDone()); - assertEquals(channel, future.join()); - verify(clock).millis(); - assertTrue(latestAuthMillisFuture.isDone()); - assertEquals(time, latestAuthMillisFuture.join()); - } - - @Test - void shouldFailToInitializeChannelWhenErrorIsReceived() { - var future = protocol.initializeChannel( - channel, - "MyDriver/2.2.1", - null, - Collections.emptyMap(), - RoutingContext.EMPTY, - null, - mock(Clock.class), - new CompletableFuture<>(), - valueFactory) - .toCompletableFuture(); - - assertEquals(1, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertEquals(1, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - messageDispatcher.handleFailureMessage( - GqlErrorUtil.gqlError("Neo.TransientError.General.DatabaseUnavailable", "Error!")); - - assertTrue(future.isDone()); - assertTrue(future.isCompletedExceptionally()); - } - - @Test - void shouldSendRoute() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - given(connection.write(any(), any())) - .willAnswer((Answer>) invocation -> { - var handler = (RunResponseHandler) invocation.getArgument(1); - handler.onSuccess(Map.of("fields", value(List.of("ttl", "servers")))); - return CompletableFuture.completedStage(null); - }) - .willAnswer((Answer>) invocation -> { - var handler = (PullResponseHandlerImpl) invocation.getArgument(1); - handler.onRecord(new Value[] { - value(1000), - value(List.of( - value(Map.of( - "role", - value("ROUTE"), - "addresses", - value(List.of(value("192.168.0.1:7867"))))), - value(Map.of( - "role", - value("WRITE"), - "addresses", - value(List.of(value("192.168.0.1:7867"))))), - value(Map.of( - "role", - value("READ"), - "addresses", - value(List.of(value("192.168.0.1:7867"))))))) - }); - handler.onSuccess(emptyMap()); - return CompletableFuture.completedStage(null); - }); - var routeFuture = new CompletableFuture(); - var handler = new MessageHandler() { - @Override - public void onError(Throwable throwable) { - routeFuture.completeExceptionally(throwable); - } - - @Override - public void onSummary(RouteSummary summary) { - routeFuture.complete(summary); - } - }; - - protocol.route( - connection, - Collections.emptyMap(), - Collections.emptySet(), - "neo4j", - null, - handler, - mock(Clock.class), - NoopLoggingProvider.INSTANCE, - valueFactory) - .toCompletableFuture() - .join(); - - var summary = routeFuture.join(); - assertEquals(summary.clusterComposition().expirationTimestamp(), TimeUnit.SECONDS.toMillis(1000)); - assertEquals(summary.clusterComposition().routers().size(), 1); - assertEquals(summary.clusterComposition().writers().size(), 1); - assertEquals(summary.clusterComposition().readers().size(), 1); - } - - @Test - void shouldBeginTransactionWithoutBookmark() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarks() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx100"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarksAndConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx4242"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldCommitTransaction() { - var bookmarkString = "neo4j:bookmark:v1:tx4242"; - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var commitHandler = (CommitTxResponseHandler) invocation.getArgument(1); - commitHandler.onSuccess(Map.of("bookmark", value(bookmarkString))); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.commitTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(CommitMessage.COMMIT), any(CommitTxResponseHandler.class)); - then(handler).should().onSummary(bookmarkString); - } - - @Test - void shouldRollbackTransaction() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var rollbackHandler = (RollbackTxResponseHandler) invocation.getArgument(1); - rollbackHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.rollbackTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(RollbackMessage.ROLLBACK), any(RollbackTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx65"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse(Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx163"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInUnmanagedTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(false, null, Collections.emptyMap(), mode); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForSuccessRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(true); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForFailureRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(false); - } - - @Test - void databaseNameInBeginTransaction() { - testDatabaseNameSupport(false); - } - - @Test - void databaseNameForAutoCommitTransactions() { - testDatabaseNameSupport(true); - } - - @Test - void shouldSupportDatabaseNameInBeginTransaction() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.beginTransaction( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldNotSupportDatabaseNameForAutoCommitTransactions() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.runAuto( - connection, - database("foo"), - AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldReturnFailedStageWithNoConnectionInteractionsOnTelemetry() { - var connection = mock(Connection.class); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var future = protocol.telemetry(connection, 1, handler).toCompletableFuture(); - - assertTrue(future.isCompletedExceptionally()); - then(connection).shouldHaveNoInteractions(); - } - - @SuppressWarnings("SameReturnValue") - private BoltProtocol createProtocol() { - return BoltProtocolV4.INSTANCE; - } - - private Class expectedMessageFormatType() { - return MessageFormatV4.class; - } - - private void testFailedRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onFailure(error); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onError(error); - } - - private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedRunStage = CompletableFuture.completedStage(null); - var expectedPullStage = CompletableFuture.completedStage(null); - var newBookmarkValue = "neo4j:bookmark:v1:tx98765"; - given(connection.write(any(), any())) - .willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedRunStage; - }) - .willAnswer((Answer>) invocation -> { - var pullHandler = (PullResponseHandlerImpl) invocation.getArgument(1); - pullHandler.onSuccess(Map.of("has_more", value(false), "bookmark", value(newBookmarkValue))); - return expectedPullStage; - }); - @SuppressWarnings("unchecked") - var runHandler = (MessageHandler) mock(MessageHandler.class); - var pullHandler = mock(PullMessageHandler.class); - - var runStage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - runHandler, - NoopLoggingProvider.INSTANCE, - valueFactory); - var pullStage = protocol.pull(connection, 0, UNLIMITED_FETCH_SIZE, pullHandler, valueFactory); - - assertEquals(expectedRunStage, runStage); - assertEquals(expectedPullStage, pullStage); - var runMessage = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(runMessage), any(RunResponseHandler.class)); - var pullMessage = new PullMessage(UNLIMITED_FETCH_SIZE, 0L, valueFactory); - then(connection).should().write(eq(pullMessage), any(PullResponseHandlerImpl.class)); - then(runHandler).should().onSummary(any()); - then(pullHandler) - .should() - .onSummary(new PullResponseHandlerImpl.PullSummaryImpl( - false, Map.of("has_more", value(false), "bookmark", value(newBookmarkValue)))); - } - - private void testRunInUnmanagedTransactionAndWaitForRunResponse(boolean success) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - if (success) { - runHandler.onSuccess(emptyMap()); - } else { - runHandler.onFailure(error); - } - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - if (success) { - then(handler).should().onSummary(any()); - } else { - then(handler).should().onError(error); - } - } - - private void testRunAndWaitForRunResponse( - boolean autoCommitTx, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var initialBookmarks = Collections.singleton("neo4j:bookmark:v1:tx987"); - - if (autoCommitTx) { - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - initialBookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - initialBookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private void testDatabaseNameSupport(boolean autoCommitTx) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - if (autoCommitTx) { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - AccessMode.WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private static Value value(Object value) { - return valueFactory.value(value); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v4/MessageFormatV4Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v4/MessageFormatV4Test.java deleted file mode 100644 index 4d90c5a0b1..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v4/MessageFormatV4Test.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v4; - -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.mockito.Mockito.mock; - -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonMessageReader; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -/** - * The MessageFormat under tests is the one provided by the {@link BoltProtocolV4} and not an specific class implementation. - *

- * It's done on this way to make easy to replace the implementation and still getting the same behaviour. - */ -class MessageFormatV4Test { - private static final MessageFormat format = BoltProtocolV4.INSTANCE.createMessageFormat(); - - @Test - void shouldCreateCorrectWriter() { - var writer = format.newWriter(mock(PackOutput.class), mock(ValueFactory.class)); - - assertInstanceOf(MessageWriterV4.class, writer); - } - - @Test - void shouldCreateCorrectReader() { - var reader = format.newReader(mock(PackInput.class), mock(ValueFactory.class)); - - assertInstanceOf(CommonMessageReader.class, reader); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v4/MessageReaderV4Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v4/MessageReaderV4Test.java deleted file mode 100644 index 9d246a1232..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v4/MessageReaderV4Test.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v4; - -import static java.util.Arrays.asList; -import static java.util.Calendar.APRIL; -import static java.util.Calendar.AUGUST; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.HashMap; -import java.util.List; -import java.util.stream.Stream; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.FailureMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.IgnoredMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.RecordMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.SuccessMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.AbstractMessageReaderTestBase; - -/** - * The MessageReader under tests is the one provided by the {@link BoltProtocolV4} and not an specific class implementation. - *

- * It's done on this way to make easy to replace the implementation and still getting the same behaviour. - */ -public class MessageReaderV4Test extends AbstractMessageReaderTestBase { - - @Override - protected Stream supportedMessages() { - return Stream.of( - // V2 Record types - record(valueFactory.point(42, 120.65, -99.2)), - record(valueFactory.point(42, 85.391, 98.8, 11.1)), - record(valueFactory.value(LocalDate.of(2012, AUGUST, 3))), - record(valueFactory.value(OffsetTime.of(23, 59, 59, 999, ZoneOffset.MAX))), - record(valueFactory.value(LocalTime.of(12, 25))), - record(valueFactory.value(LocalDateTime.of(1999, APRIL, 3, 19, 5, 5, 100_200_300))), - record(valueFactory.value( - ZonedDateTime.of(1823, 1, 12, 23, 59, 59, 999_999_999, ZoneOffset.ofHoursMinutes(-7, -15)))), - record(valueFactory.value( - ZonedDateTime.of(1823, 1, 12, 23, 59, 59, 999_999_999, ZoneId.of("Europe/Stockholm")))), - record(valueFactory.isoDuration( - Long.MAX_VALUE - 1, Integer.MAX_VALUE - 1, Short.MAX_VALUE - 1, Byte.MAX_VALUE - 1)), - record(valueFactory.isoDuration(17, 22, 99, 15)), - - // Bolt previous versions valid messages - new FailureMessage("Hello", "World!"), - IgnoredMessage.IGNORED, - new SuccessMessage(new HashMap<>()), - record(valueFactory.value(1337L)), - record(valueFactory.value(List.of("cat", valueFactory.value(null), "dog", valueFactory.value(null)))), - record(valueFactory.value(List.of("k", valueFactory.value(12), "a", valueFactory.value("banana")))), - record(valueFactory.value(asList( - valueFactory.value("k"), - valueFactory.value(12), - valueFactory.value("a"), - valueFactory.value("banana")))), - - // V3 Record Types - record(valueFactory.emptyNodeValue()), - record(valueFactory.filledNodeValue()), - record(valueFactory.emptyRelationshipValue()), - record(valueFactory.filledRelationshipValue()), - record(valueFactory.filledPathValue()), - record(valueFactory.emptyPathValue())); - } - - @Override - protected Stream unsupportedMessages() { - return Stream.of(DiscardAllMessage.DISCARD_ALL); - } - - @Override - protected MessageFormat.Reader newReader(PackInput input) { - return BoltProtocolV4.INSTANCE.createMessageFormat().newReader(input, valueFactory); - } - - private Message record(Value value) { - return new RecordMessage(new Value[] {value}); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v4/MessageWriterV4Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v4/MessageWriterV4Test.java deleted file mode 100644 index 3cb42eabe2..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v4/MessageWriterV4Test.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v4; - -import static java.time.Duration.ofSeconds; -import static java.util.Calendar.DECEMBER; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.neo4j.driver.internal.bolt.api.AccessMode.READ; -import static org.neo4j.driver.internal.bolt.api.AccessMode.WRITE; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage.COMMIT; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage.DISCARD_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage.GOODBYE; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullAllMessage.PULL_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage.RESET; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage.ROLLBACK; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.Collections; -import java.util.Map; -import java.util.stream.Stream; -import org.neo4j.driver.internal.bolt.basicimpl.impl.BoltAgentUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3.BoltProtocolV3; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.AbstractMessageWriterTestBase; - -/** - * The MessageWriter under tests is the one provided by the {@link BoltProtocolV3} and not an specific class - * implementation. - *

- * It's done on this way to make easy to replace the implementation and still getting the same behaviour. - */ -class MessageWriterV4Test extends AbstractMessageWriterTestBase { - @Override - protected MessageFormat.Writer newWriter(PackOutput output) { - return BoltProtocolV4.INSTANCE.createMessageFormat().newWriter(output, valueFactory); - } - - @Override - protected Stream supportedMessages() { - return Stream.of( - // Bolt V2 Data Types - unmanagedTxRunMessage("RETURN $point", singletonMap("point", valueFactory.point(42, 12.99, -180.0))), - unmanagedTxRunMessage( - "RETURN $point", singletonMap("point", valueFactory.point(42, 0.51, 2.99, 100.123))), - unmanagedTxRunMessage( - "RETURN $date", singletonMap("date", valueFactory.value(LocalDate.ofEpochDay(2147483650L)))), - unmanagedTxRunMessage( - "RETURN $time", - singletonMap("time", valueFactory.value(OffsetTime.of(4, 16, 20, 999, ZoneOffset.MIN)))), - unmanagedTxRunMessage( - "RETURN $time", singletonMap("time", valueFactory.value(LocalTime.of(12, 9, 18, 999_888)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", valueFactory.value(LocalDateTime.of(2049, DECEMBER, 12, 17, 25, 49, 199)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value(ZonedDateTime.of( - 2000, 1, 10, 12, 2, 49, 300, ZoneOffset.ofHoursMinutes(9, 30))))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value( - ZonedDateTime.of(2000, 1, 10, 12, 2, 49, 300, ZoneId.of("Europe/Stockholm"))))), - - // New Bolt V4 messages - new PullMessage(100, 200, valueFactory), - new DiscardMessage(300, 400, valueFactory), - - // Bolt V3 messages - new HelloMessage( - "MyDriver/1.2.3", - BoltAgentUtil.VALUE, - Map.of( - "scheme", - valueFactory.value("basic"), - "principal", - valueFactory.value("neo4j"), - "credentials", - valueFactory.value("neo4j")), - Collections.emptyMap(), - false, - null, - false, - valueFactory), - GOODBYE, - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - READ, - defaultDatabase(), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - WRITE, - database("foo"), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - COMMIT, - ROLLBACK, - RESET, - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - defaultDatabase(), - READ, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - database("foo"), - WRITE, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN 1", Collections.emptyMap()), - - // Bolt V3 messages with struct values - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - defaultDatabase(), - READ, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - database("foo"), - WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN $x", singletonMap("x", valueFactory.point(42, 1, 2, 3)))); - } - - @Override - protected Stream unsupportedMessages() { - return Stream.of( - // Bolt V1, V2 and V3 messages - PULL_ALL, DISCARD_ALL); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v41/BoltProtocolV41Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v41/BoltProtocolV41Test.java deleted file mode 100644 index 1cf64de37b..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v41/BoltProtocolV41Test.java +++ /dev/null @@ -1,814 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v41; - -import static java.time.Duration.ofSeconds; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import io.netty.channel.embedded.EmbeddedChannel; -import java.time.Clock; -import java.time.Duration; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.mockito.stubbing.Answer; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.GqlErrorUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.BeginTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.CommitTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.PullResponseHandlerImpl; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RollbackTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RunResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.PullMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v4.MessageFormatV4; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public final class BoltProtocolV41Test { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private static final String query = "RETURN $x"; - private static final Map query_params = singletonMap("x", value(42)); - private static final long UNLIMITED_FETCH_SIZE = -1; - private static final Duration txTimeout = ofSeconds(12); - private static final Map txMetadata = singletonMap("x", value(42)); - - private final BoltProtocol protocol = createProtocol(); - private final EmbeddedChannel channel = new EmbeddedChannel(); - private final InboundMessageDispatcher messageDispatcher = - new InboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE); - - @SuppressWarnings("SameReturnValue") - private BoltProtocol createProtocol() { - return BoltProtocolV41.INSTANCE; - } - - @BeforeEach - void beforeEach() { - ChannelAttributes.setMessageDispatcher(channel, messageDispatcher); - } - - @AfterEach - void afterEach() { - channel.finishAndReleaseAll(); - } - - @Test - void shouldCreateMessageFormat() { - assertInstanceOf(expectedMessageFormatType(), protocol.createMessageFormat()); - } - - @Test - void shouldInitializeChannel() { - var clock = mock(Clock.class); - var time = 1L; - when(clock.millis()).thenReturn(time); - - var latestAuthMillisFuture = new CompletableFuture(); - - var future = protocol.initializeChannel( - channel, - "MyDriver/0.0.1", - null, - Collections.emptyMap(), - RoutingContext.EMPTY, - null, - clock, - latestAuthMillisFuture, - valueFactory) - .toCompletableFuture(); - - assertEquals(1, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertEquals(1, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - var metadata = Map.of( - "server", value("Neo4j/3.5.0"), - "connection_id", value("bolt-42")); - - messageDispatcher.handleSuccessMessage(metadata); - - assertTrue(future.isDone()); - assertEquals(channel, future.join()); - verify(clock).millis(); - assertTrue(latestAuthMillisFuture.isDone()); - assertEquals(time, latestAuthMillisFuture.join()); - } - - @Test - void shouldFailToInitializeChannelWhenErrorIsReceived() { - var future = protocol.initializeChannel( - channel, - "MyDriver/2.2.1", - null, - Collections.emptyMap(), - RoutingContext.EMPTY, - null, - mock(Clock.class), - new CompletableFuture<>(), - valueFactory) - .toCompletableFuture(); - - assertEquals(1, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertEquals(1, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - messageDispatcher.handleFailureMessage( - GqlErrorUtil.gqlError("Neo.TransientError.General.DatabaseUnavailable", "Error!")); - - assertTrue(future.isDone()); - assertTrue(future.isCompletedExceptionally()); - } - - @Test - void shouldBeginTransactionWithoutBookmark() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarks() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx100"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarksAndConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx4242"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldCommitTransaction() { - var bookmarkString = "neo4j:bookmark:v1:tx4242"; - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var commitHandler = (CommitTxResponseHandler) invocation.getArgument(1); - commitHandler.onSuccess(Map.of("bookmark", value(bookmarkString))); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.commitTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(CommitMessage.COMMIT), any(CommitTxResponseHandler.class)); - then(handler).should().onSummary(bookmarkString); - } - - @Test - void shouldRollbackTransaction() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var rollbackHandler = (RollbackTxResponseHandler) invocation.getArgument(1); - rollbackHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.rollbackTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(RollbackMessage.ROLLBACK), any(RollbackTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx65"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse(Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx163"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInUnmanagedTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(false, null, Collections.emptyMap(), mode); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForSuccessRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(true); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForFailureRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(false); - } - - @Test - void databaseNameInBeginTransaction() { - testDatabaseNameSupport(false); - } - - @Test - void databaseNameForAutoCommitTransactions() { - testDatabaseNameSupport(true); - } - - @Test - void shouldSupportDatabaseNameInBeginTransaction() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.beginTransaction( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldNotSupportDatabaseNameForAutoCommitTransactions() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.runAuto( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldReturnFailedStageWithNoConnectionInteractionsOnTelemetry() { - var connection = mock(Connection.class); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var future = protocol.telemetry(connection, 1, handler).toCompletableFuture(); - - assertTrue(future.isCompletedExceptionally()); - then(connection).shouldHaveNoInteractions(); - } - - private Class expectedMessageFormatType() { - return MessageFormatV4.class; - } - - private void testFailedRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onFailure(error); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onError(error); - } - - private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedRunStage = CompletableFuture.completedStage(null); - var expectedPullStage = CompletableFuture.completedStage(null); - var newBookmarkValue = "neo4j:bookmark:v1:tx98765"; - given(connection.write(any(), any())) - .willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedRunStage; - }) - .willAnswer((Answer>) invocation -> { - var pullHandler = (PullResponseHandlerImpl) invocation.getArgument(1); - pullHandler.onSuccess(Map.of("has_more", value(false), "bookmark", value(newBookmarkValue))); - return expectedPullStage; - }); - @SuppressWarnings("unchecked") - var runHandler = (MessageHandler) mock(MessageHandler.class); - var pullHandler = mock(PullMessageHandler.class); - - var runStage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - runHandler, - NoopLoggingProvider.INSTANCE, - valueFactory); - var pullStage = protocol.pull(connection, 0, UNLIMITED_FETCH_SIZE, pullHandler, valueFactory); - - assertEquals(expectedRunStage, runStage); - assertEquals(expectedPullStage, pullStage); - var runMessage = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(runMessage), any(RunResponseHandler.class)); - var pullMessage = new PullMessage(UNLIMITED_FETCH_SIZE, 0L, valueFactory); - then(connection).should().write(eq(pullMessage), any(PullResponseHandlerImpl.class)); - then(runHandler).should().onSummary(any()); - then(pullHandler) - .should() - .onSummary(new PullResponseHandlerImpl.PullSummaryImpl( - false, Map.of("has_more", value(false), "bookmark", value(newBookmarkValue)))); - } - - private void testRunInUnmanagedTransactionAndWaitForRunResponse(boolean success) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - if (success) { - runHandler.onSuccess(emptyMap()); - } else { - runHandler.onFailure(error); - } - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - if (success) { - then(handler).should().onSummary(any()); - } else { - then(handler).should().onError(error); - } - } - - private void testRunAndWaitForRunResponse( - boolean autoCommitTx, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var initialBookmarks = Collections.singleton("neo4j:bookmark:v1:tx987"); - - if (autoCommitTx) { - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - initialBookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - initialBookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private void testDatabaseNameSupport(boolean autoCommitTx) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - if (autoCommitTx) { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private static Value value(Object value) { - return valueFactory.value(value); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v41/MessageFormatV41Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v41/MessageFormatV41Test.java deleted file mode 100644 index 02d1b64c04..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v41/MessageFormatV41Test.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v41; - -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.mockito.Mockito.mock; - -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonMessageReader; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3.BoltProtocolV3; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v4.MessageWriterV4; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -/** - * The MessageFormat under tests is the one provided by the {@link BoltProtocolV3} and not an specific class implementation. - *

- * It's done on this way to make easy to replace the implementation and still getting the same behaviour. - */ -class MessageFormatV41Test { - private static final MessageFormat format = BoltProtocolV41.INSTANCE.createMessageFormat(); - - @Test - void shouldCreateCorrectWriter() { - var writer = format.newWriter(mock(PackOutput.class), mock(ValueFactory.class)); - - assertInstanceOf(MessageWriterV4.class, writer); - } - - @Test - void shouldCreateCorrectReader() { - var reader = format.newReader(mock(PackInput.class), mock(ValueFactory.class)); - - assertInstanceOf(CommonMessageReader.class, reader); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v41/MessageReaderV41Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v41/MessageReaderV41Test.java deleted file mode 100644 index a1a9c0385d..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v41/MessageReaderV41Test.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v41; - -import static java.util.Arrays.asList; -import static java.util.Calendar.APRIL; -import static java.util.Calendar.AUGUST; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.HashMap; -import java.util.List; -import java.util.stream.Stream; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.FailureMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.IgnoredMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.RecordMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.SuccessMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.AbstractMessageReaderTestBase; - -/** - * The MessageReader under tests is the one provided by the {@link BoltProtocolV41} and not an specific class implementation. - *

- * It's done on this way to make easy to replace the implementation and still getting the same behaviour. - */ -public class MessageReaderV41Test extends AbstractMessageReaderTestBase { - - @Override - protected Stream supportedMessages() { - return Stream.of( - // V2 Record types - record(valueFactory.point(42, 120.65, -99.2)), - record(valueFactory.point(42, 85.391, 98.8, 11.1)), - record(valueFactory.value(LocalDate.of(2012, AUGUST, 3))), - record(valueFactory.value(OffsetTime.of(23, 59, 59, 999, ZoneOffset.MAX))), - record(valueFactory.value(LocalTime.of(12, 25))), - record(valueFactory.value(LocalDateTime.of(1999, APRIL, 3, 19, 5, 5, 100_200_300))), - record(valueFactory.value( - ZonedDateTime.of(1823, 1, 12, 23, 59, 59, 999_999_999, ZoneOffset.ofHoursMinutes(-7, -15)))), - record(valueFactory.value( - ZonedDateTime.of(1823, 1, 12, 23, 59, 59, 999_999_999, ZoneId.of("Europe/Stockholm")))), - record(valueFactory.isoDuration( - Long.MAX_VALUE - 1, Integer.MAX_VALUE - 1, Short.MAX_VALUE - 1, Byte.MAX_VALUE - 1)), - record(valueFactory.isoDuration(17, 22, 99, 15)), - - // Bolt previous versions valid messages - new FailureMessage("Hello", "World!"), - IgnoredMessage.IGNORED, - new SuccessMessage(new HashMap<>()), - record(valueFactory.value(1337L)), - record(valueFactory.value(List.of("cat", valueFactory.value(null), "dog", valueFactory.value(null)))), - record(valueFactory.value(List.of("k", valueFactory.value(12), "a", valueFactory.value("banana")))), - record(valueFactory.value(asList( - valueFactory.value("k"), - valueFactory.value(12), - valueFactory.value("a"), - valueFactory.value("banana")))), - - // V3 Record Types - record(valueFactory.emptyNodeValue()), - record(valueFactory.filledNodeValue()), - record(valueFactory.emptyRelationshipValue()), - record(valueFactory.filledRelationshipValue()), - record(valueFactory.filledPathValue()), - record(valueFactory.emptyPathValue())); - } - - @Override - protected Stream unsupportedMessages() { - return Stream.of(DiscardAllMessage.DISCARD_ALL); - } - - @Override - protected MessageFormat.Reader newReader(PackInput input) { - return BoltProtocolV41.INSTANCE.createMessageFormat().newReader(input, valueFactory); - } - - private Message record(Value value) { - return new RecordMessage(new Value[] {value}); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v41/MessageWriterV41Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v41/MessageWriterV41Test.java deleted file mode 100644 index 6e2be6622c..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v41/MessageWriterV41Test.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v41; - -import static java.time.Duration.ofSeconds; -import static java.util.Calendar.DECEMBER; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.neo4j.driver.internal.bolt.api.AccessMode.READ; -import static org.neo4j.driver.internal.bolt.api.AccessMode.WRITE; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage.COMMIT; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage.DISCARD_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage.GOODBYE; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullAllMessage.PULL_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage.RESET; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage.ROLLBACK; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.Collections; -import java.util.Map; -import java.util.stream.Stream; -import org.neo4j.driver.internal.bolt.basicimpl.impl.BoltAgentUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.AbstractMessageWriterTestBase; - -/** - * The MessageWriter under tests is the one provided by the {@link BoltProtocolV41} and not an specific class - * implementation. - *

- * It's done on this way to make easy to replace the implementation and still getting the same behaviour. - */ -class MessageWriterV41Test extends AbstractMessageWriterTestBase { - @Override - protected MessageFormat.Writer newWriter(PackOutput output) { - return BoltProtocolV41.INSTANCE.createMessageFormat().newWriter(output, valueFactory); - } - - @Override - protected Stream supportedMessages() { - return Stream.of( - // Bolt V2 Data Types - unmanagedTxRunMessage("RETURN $point", singletonMap("point", valueFactory.point(42, 12.99, -180.0))), - unmanagedTxRunMessage( - "RETURN $point", singletonMap("point", valueFactory.point(42, 0.51, 2.99, 100.123))), - unmanagedTxRunMessage( - "RETURN $date", singletonMap("date", valueFactory.value(LocalDate.ofEpochDay(2147483650L)))), - unmanagedTxRunMessage( - "RETURN $time", - singletonMap("time", valueFactory.value(OffsetTime.of(4, 16, 20, 999, ZoneOffset.MIN)))), - unmanagedTxRunMessage( - "RETURN $time", singletonMap("time", valueFactory.value(LocalTime.of(12, 9, 18, 999_888)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", valueFactory.value(LocalDateTime.of(2049, DECEMBER, 12, 17, 25, 49, 199)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value(ZonedDateTime.of( - 2000, 1, 10, 12, 2, 49, 300, ZoneOffset.ofHoursMinutes(9, 30))))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value( - ZonedDateTime.of(2000, 1, 10, 12, 2, 49, 300, ZoneId.of("Europe/Stockholm"))))), - - // New Bolt V4 messages - new PullMessage(100, 200, valueFactory), - new DiscardMessage(300, 400, valueFactory), - - // Bolt V3 messages - new HelloMessage( - "MyDriver/1.2.3", - BoltAgentUtil.VALUE, - Map.of( - "scheme", - valueFactory.value("basic"), - "principal", - valueFactory.value("neo4j"), - "credentials", - valueFactory.value("neo4j")), - Collections.emptyMap(), - false, - null, - false, - valueFactory), - GOODBYE, - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - READ, - defaultDatabase(), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - WRITE, - database("foo"), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - COMMIT, - ROLLBACK, - RESET, - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - defaultDatabase(), - READ, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - database("foo"), - WRITE, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN 1", Collections.emptyMap()), - - // Bolt V3 messages with struct values - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - defaultDatabase(), - READ, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - database("foo"), - WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN $x", singletonMap("x", valueFactory.point(42, 1, 2, 3)))); - } - - @Override - protected Stream unsupportedMessages() { - return Stream.of( - // Bolt V1, V2 and V3 messages - PULL_ALL, DISCARD_ALL); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v42/BoltProtocolV42Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v42/BoltProtocolV42Test.java deleted file mode 100644 index 2749a5f0ae..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v42/BoltProtocolV42Test.java +++ /dev/null @@ -1,814 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v42; - -import static java.time.Duration.ofSeconds; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import io.netty.channel.embedded.EmbeddedChannel; -import java.time.Clock; -import java.time.Duration; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.mockito.stubbing.Answer; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.GqlErrorUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.BeginTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.CommitTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.PullResponseHandlerImpl; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RollbackTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RunResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.PullMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v4.MessageFormatV4; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public final class BoltProtocolV42Test { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private static final String query = "RETURN $x"; - private static final Map query_params = singletonMap("x", value(42)); - private static final long UNLIMITED_FETCH_SIZE = -1; - private static final Duration txTimeout = ofSeconds(12); - private static final Map txMetadata = singletonMap("x", value(42)); - - private final BoltProtocol protocol = createProtocol(); - private final EmbeddedChannel channel = new EmbeddedChannel(); - private final InboundMessageDispatcher messageDispatcher = - new InboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE); - - @SuppressWarnings("SameReturnValue") - private BoltProtocol createProtocol() { - return BoltProtocolV42.INSTANCE; - } - - @BeforeEach - void beforeEach() { - ChannelAttributes.setMessageDispatcher(channel, messageDispatcher); - } - - @AfterEach - void afterEach() { - channel.finishAndReleaseAll(); - } - - @Test - void shouldCreateMessageFormat() { - assertInstanceOf(expectedMessageFormatType(), protocol.createMessageFormat()); - } - - @Test - void shouldInitializeChannel() { - var clock = mock(Clock.class); - var time = 1L; - when(clock.millis()).thenReturn(time); - - var latestAuthMillisFuture = new CompletableFuture(); - - var future = protocol.initializeChannel( - channel, - "MyDriver/0.0.1", - null, - Collections.emptyMap(), - RoutingContext.EMPTY, - null, - clock, - latestAuthMillisFuture, - valueFactory) - .toCompletableFuture(); - - assertEquals(1, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertEquals(1, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - var metadata = Map.of( - "server", value("Neo4j/3.5.0"), - "connection_id", value("bolt-42")); - - messageDispatcher.handleSuccessMessage(metadata); - - assertTrue(future.isDone()); - assertEquals(channel, future.join()); - verify(clock).millis(); - assertTrue(latestAuthMillisFuture.isDone()); - assertEquals(time, latestAuthMillisFuture.join()); - } - - @Test - void shouldFailToInitializeChannelWhenErrorIsReceived() { - var future = protocol.initializeChannel( - channel, - "MyDriver/2.2.1", - null, - Collections.emptyMap(), - RoutingContext.EMPTY, - null, - mock(Clock.class), - new CompletableFuture<>(), - valueFactory) - .toCompletableFuture(); - - assertEquals(1, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertEquals(1, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - messageDispatcher.handleFailureMessage( - GqlErrorUtil.gqlError("Neo.TransientError.General.DatabaseUnavailable", "Error!")); - - assertTrue(future.isDone()); - assertTrue(future.isCompletedExceptionally()); - } - - @Test - void shouldBeginTransactionWithoutBookmark() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarks() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx100"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarksAndConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx4242"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldCommitTransaction() { - var bookmarkString = "neo4j:bookmark:v1:tx4242"; - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var commitHandler = (CommitTxResponseHandler) invocation.getArgument(1); - commitHandler.onSuccess(Map.of("bookmark", value(bookmarkString))); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.commitTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(CommitMessage.COMMIT), any(CommitTxResponseHandler.class)); - then(handler).should().onSummary(bookmarkString); - } - - @Test - void shouldRollbackTransaction() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var rollbackHandler = (RollbackTxResponseHandler) invocation.getArgument(1); - rollbackHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.rollbackTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(RollbackMessage.ROLLBACK), any(RollbackTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx65"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse(Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx163"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInUnmanagedTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(false, null, Collections.emptyMap(), mode); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForSuccessRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(true); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForFailureRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(false); - } - - @Test - void databaseNameInBeginTransaction() { - testDatabaseNameSupport(false); - } - - @Test - void databaseNameForAutoCommitTransactions() { - testDatabaseNameSupport(true); - } - - @Test - void shouldSupportDatabaseNameInBeginTransaction() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.beginTransaction( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldNotSupportDatabaseNameForAutoCommitTransactions() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.runAuto( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldReturnFailedStageWithNoConnectionInteractionsOnTelemetry() { - var connection = mock(Connection.class); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var future = protocol.telemetry(connection, 1, handler).toCompletableFuture(); - - assertTrue(future.isCompletedExceptionally()); - then(connection).shouldHaveNoInteractions(); - } - - private Class expectedMessageFormatType() { - return MessageFormatV4.class; - } - - private void testFailedRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onFailure(error); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onError(error); - } - - private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedRunStage = CompletableFuture.completedStage(null); - var expectedPullStage = CompletableFuture.completedStage(null); - var newBookmarkValue = "neo4j:bookmark:v1:tx98765"; - given(connection.write(any(), any())) - .willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedRunStage; - }) - .willAnswer((Answer>) invocation -> { - var pullHandler = (PullResponseHandlerImpl) invocation.getArgument(1); - pullHandler.onSuccess(Map.of("has_more", value(false), "bookmark", value(newBookmarkValue))); - return expectedPullStage; - }); - @SuppressWarnings("unchecked") - var runHandler = (MessageHandler) mock(MessageHandler.class); - var pullHandler = mock(PullMessageHandler.class); - - var runStage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - runHandler, - NoopLoggingProvider.INSTANCE, - valueFactory); - var pullStage = protocol.pull(connection, 0, UNLIMITED_FETCH_SIZE, pullHandler, valueFactory); - - assertEquals(expectedRunStage, runStage); - assertEquals(expectedPullStage, pullStage); - var runMessage = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(runMessage), any(RunResponseHandler.class)); - var pullMessage = new PullMessage(UNLIMITED_FETCH_SIZE, 0L, valueFactory); - then(connection).should().write(eq(pullMessage), any(PullResponseHandlerImpl.class)); - then(runHandler).should().onSummary(any()); - then(pullHandler) - .should() - .onSummary(new PullResponseHandlerImpl.PullSummaryImpl( - false, Map.of("has_more", value(false), "bookmark", value(newBookmarkValue)))); - } - - private void testRunInUnmanagedTransactionAndWaitForRunResponse(boolean success) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - if (success) { - runHandler.onSuccess(emptyMap()); - } else { - runHandler.onFailure(error); - } - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - if (success) { - then(handler).should().onSummary(any()); - } else { - then(handler).should().onError(error); - } - } - - private void testRunAndWaitForRunResponse( - boolean autoCommitTx, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var initialBookmarks = Collections.singleton("neo4j:bookmark:v1:tx987"); - - if (autoCommitTx) { - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - initialBookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - initialBookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private void testDatabaseNameSupport(boolean autoCommitTx) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - if (autoCommitTx) { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private static Value value(Object value) { - return valueFactory.value(value); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v42/MessageFormatV42Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v42/MessageFormatV42Test.java deleted file mode 100644 index a59e480efe..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v42/MessageFormatV42Test.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v42; - -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.mockito.Mockito.mock; - -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonMessageReader; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v4.MessageWriterV4; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -/** - * The MessageFormat under tests is the one provided by the {@link BoltProtocolV42} and not an specific class implementation. - *

- * It's done on this way to make easy to replace the implementation and still getting the same behaviour. - */ -class MessageFormatV42Test { - private static final MessageFormat format = BoltProtocolV42.INSTANCE.createMessageFormat(); - - @Test - void shouldCreateCorrectWriter() { - var writer = format.newWriter(mock(PackOutput.class), mock(ValueFactory.class)); - - assertInstanceOf(MessageWriterV4.class, writer); - } - - @Test - void shouldCreateCorrectReader() { - var reader = format.newReader(mock(PackInput.class), mock(ValueFactory.class)); - - assertInstanceOf(CommonMessageReader.class, reader); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v42/MessageReaderV42Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v42/MessageReaderV42Test.java deleted file mode 100644 index ba8a859627..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v42/MessageReaderV42Test.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v42; - -import static java.util.Arrays.asList; -import static java.util.Calendar.APRIL; -import static java.util.Calendar.AUGUST; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.HashMap; -import java.util.List; -import java.util.stream.Stream; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.FailureMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.IgnoredMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.RecordMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.SuccessMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.AbstractMessageReaderTestBase; - -/** - * The MessageReader under tests is the one provided by the {@link BoltProtocolV42} and not an specific class implementation. - *

- * It's done on this way to make easy to replace the implementation and still getting the same behaviour. - */ -public class MessageReaderV42Test extends AbstractMessageReaderTestBase { - - @Override - protected Stream supportedMessages() { - return Stream.of( - // V2 Record types - record(valueFactory.point(42, 120.65, -99.2)), - record(valueFactory.point(42, 85.391, 98.8, 11.1)), - record(valueFactory.value(LocalDate.of(2012, AUGUST, 3))), - record(valueFactory.value(OffsetTime.of(23, 59, 59, 999, ZoneOffset.MAX))), - record(valueFactory.value(LocalTime.of(12, 25))), - record(valueFactory.value(LocalDateTime.of(1999, APRIL, 3, 19, 5, 5, 100_200_300))), - record(valueFactory.value( - ZonedDateTime.of(1823, 1, 12, 23, 59, 59, 999_999_999, ZoneOffset.ofHoursMinutes(-7, -15)))), - record(valueFactory.value( - ZonedDateTime.of(1823, 1, 12, 23, 59, 59, 999_999_999, ZoneId.of("Europe/Stockholm")))), - record(valueFactory.isoDuration( - Long.MAX_VALUE - 1, Integer.MAX_VALUE - 1, Short.MAX_VALUE - 1, Byte.MAX_VALUE - 1)), - record(valueFactory.isoDuration(17, 22, 99, 15)), - - // Bolt previous versions valid messages - new FailureMessage("Hello", "World!"), - IgnoredMessage.IGNORED, - new SuccessMessage(new HashMap<>()), - record(valueFactory.value(1337L)), - record(valueFactory.value(List.of("cat", valueFactory.value(null), "dog", valueFactory.value(null)))), - record(valueFactory.value(List.of("k", valueFactory.value(12), "a", valueFactory.value("banana")))), - record(valueFactory.value(asList( - valueFactory.value("k"), - valueFactory.value(12), - valueFactory.value("a"), - valueFactory.value("banana")))), - - // V3 Record Types - record(valueFactory.emptyNodeValue()), - record(valueFactory.filledNodeValue()), - record(valueFactory.emptyRelationshipValue()), - record(valueFactory.filledRelationshipValue()), - record(valueFactory.filledPathValue()), - record(valueFactory.emptyPathValue())); - } - - @Override - protected Stream unsupportedMessages() { - return Stream.of(DiscardAllMessage.DISCARD_ALL); - } - - @Override - protected MessageFormat.Reader newReader(PackInput input) { - return BoltProtocolV42.INSTANCE.createMessageFormat().newReader(input, valueFactory); - } - - private Message record(Value value) { - return new RecordMessage(new Value[] {value}); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v42/MessageWriterV42Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v42/MessageWriterV42Test.java deleted file mode 100644 index 09ca4a76b9..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v42/MessageWriterV42Test.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v42; - -import static java.time.Duration.ofSeconds; -import static java.util.Calendar.DECEMBER; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.neo4j.driver.internal.bolt.api.AccessMode.READ; -import static org.neo4j.driver.internal.bolt.api.AccessMode.WRITE; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage.COMMIT; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage.DISCARD_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage.GOODBYE; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullAllMessage.PULL_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage.RESET; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage.ROLLBACK; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.Collections; -import java.util.Map; -import java.util.stream.Stream; -import org.neo4j.driver.internal.bolt.basicimpl.impl.BoltAgentUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.AbstractMessageWriterTestBase; - -/** - * The MessageWriter under tests is the one provided by the {@link BoltProtocolV42} and not an specific class - * implementation. - *

- * It's done on this way to make easy to replace the implementation and still getting the same behaviour. - */ -class MessageWriterV42Test extends AbstractMessageWriterTestBase { - @Override - protected MessageFormat.Writer newWriter(PackOutput output) { - return BoltProtocolV42.INSTANCE.createMessageFormat().newWriter(output, valueFactory); - } - - @Override - protected Stream supportedMessages() { - return Stream.of( - // Bolt V2 Data Types - unmanagedTxRunMessage("RETURN $point", singletonMap("point", valueFactory.point(42, 12.99, -180.0))), - unmanagedTxRunMessage( - "RETURN $point", singletonMap("point", valueFactory.point(42, 0.51, 2.99, 100.123))), - unmanagedTxRunMessage( - "RETURN $date", singletonMap("date", valueFactory.value(LocalDate.ofEpochDay(2147483650L)))), - unmanagedTxRunMessage( - "RETURN $time", - singletonMap("time", valueFactory.value(OffsetTime.of(4, 16, 20, 999, ZoneOffset.MIN)))), - unmanagedTxRunMessage( - "RETURN $time", singletonMap("time", valueFactory.value(LocalTime.of(12, 9, 18, 999_888)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", valueFactory.value(LocalDateTime.of(2049, DECEMBER, 12, 17, 25, 49, 199)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value(ZonedDateTime.of( - 2000, 1, 10, 12, 2, 49, 300, ZoneOffset.ofHoursMinutes(9, 30))))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value( - ZonedDateTime.of(2000, 1, 10, 12, 2, 49, 300, ZoneId.of("Europe/Stockholm"))))), - - // New Bolt V4 messages - new PullMessage(100, 200, valueFactory), - new DiscardMessage(300, 400, valueFactory), - - // Bolt V3 messages - new HelloMessage( - "MyDriver/1.2.3", - BoltAgentUtil.VALUE, - Map.of( - "scheme", - valueFactory.value("basic"), - "principal", - valueFactory.value("neo4j"), - "credentials", - valueFactory.value("neo4j")), - Collections.emptyMap(), - false, - null, - false, - valueFactory), - GOODBYE, - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - READ, - defaultDatabase(), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - WRITE, - database("foo"), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - COMMIT, - ROLLBACK, - RESET, - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - defaultDatabase(), - READ, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - database("foo"), - WRITE, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN 1", Collections.emptyMap()), - - // Bolt V3 messages with struct values - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - defaultDatabase(), - READ, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - database("foo"), - WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN $x", singletonMap("x", valueFactory.point(42, 1, 2, 3)))); - } - - @Override - protected Stream unsupportedMessages() { - return Stream.of( - // Bolt V1, V2 and V3 messages - PULL_ALL, DISCARD_ALL); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v43/BoltProtocolV43Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v43/BoltProtocolV43Test.java deleted file mode 100644 index c45176caa3..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v43/BoltProtocolV43Test.java +++ /dev/null @@ -1,879 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v43; - -import static java.time.Duration.ofSeconds; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import io.netty.channel.embedded.EmbeddedChannel; -import java.time.Clock; -import java.time.Duration; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.TimeUnit; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.mockito.stubbing.Answer; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.RouteSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.GqlErrorUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.BeginTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.CommitTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.PullResponseHandlerImpl; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RollbackTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RouteMessageResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RunResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.PullMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public final class BoltProtocolV43Test { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private static final String query = "RETURN $x"; - private static final Map query_params = singletonMap("x", value(42)); - private static final long UNLIMITED_FETCH_SIZE = -1; - private static final Duration txTimeout = ofSeconds(12); - private static final Map txMetadata = singletonMap("x", value(42)); - - private final BoltProtocol protocol = createProtocol(); - private final EmbeddedChannel channel = new EmbeddedChannel(); - private final InboundMessageDispatcher messageDispatcher = - new InboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE); - - @SuppressWarnings("SameReturnValue") - private BoltProtocol createProtocol() { - return BoltProtocolV43.INSTANCE; - } - - @BeforeEach - void beforeEach() { - ChannelAttributes.setMessageDispatcher(channel, messageDispatcher); - } - - @AfterEach - void afterEach() { - channel.finishAndReleaseAll(); - } - - @Test - void shouldCreateMessageFormat() { - assertInstanceOf(expectedMessageFormatType(), protocol.createMessageFormat()); - } - - @Test - void shouldInitializeChannel() { - var clock = mock(Clock.class); - var time = 1L; - when(clock.millis()).thenReturn(time); - - var latestAuthMillisFuture = new CompletableFuture(); - - var future = protocol.initializeChannel( - channel, - "MyDriver/0.0.1", - null, - Collections.emptyMap(), - RoutingContext.EMPTY, - null, - clock, - latestAuthMillisFuture, - valueFactory) - .toCompletableFuture(); - - assertEquals(1, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertEquals(1, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - var metadata = Map.of( - "server", value("Neo4j/3.5.0"), - "connection_id", value("bolt-42")); - - messageDispatcher.handleSuccessMessage(metadata); - - assertTrue(future.isDone()); - assertEquals(channel, future.join()); - verify(clock).millis(); - assertTrue(latestAuthMillisFuture.isDone()); - assertEquals(time, latestAuthMillisFuture.join()); - } - - @Test - void shouldFailToInitializeChannelWhenErrorIsReceived() { - var future = protocol.initializeChannel( - channel, - "MyDriver/2.2.1", - null, - Collections.emptyMap(), - RoutingContext.EMPTY, - null, - mock(Clock.class), - new CompletableFuture<>(), - valueFactory) - .toCompletableFuture(); - - assertEquals(1, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertEquals(1, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - messageDispatcher.handleFailureMessage( - GqlErrorUtil.gqlError("Neo.TransientError.General.DatabaseUnavailable", "Error!")); - - assertTrue(future.isDone()); - assertTrue(future.isCompletedExceptionally()); - } - - @Test - void shouldSendRoute() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var handler = (RouteMessageResponseHandler) invocation.getArgument(1); - handler.onSuccess(Map.of( - "rt", - value(Map.of( - "ttl", value(1000), - "servers", - value(List.of( - value(Map.of( - "role", - value("ROUTE"), - "addresses", - value(List.of(value("192.168.0.1:7867"))))), - value(Map.of( - "role", - value("WRITE"), - "addresses", - value(List.of(value("192.168.0.1:7867"))))), - value(Map.of( - "role", - value("READ"), - "addresses", - value(List.of(value("192.168.0.1:7867"))))))))))); - return CompletableFuture.completedStage(null); - }); - var routeFuture = new CompletableFuture(); - var handler = new MessageHandler() { - @Override - public void onError(Throwable throwable) { - routeFuture.completeExceptionally(throwable); - } - - @Override - public void onSummary(RouteSummary summary) { - routeFuture.complete(summary); - } - }; - - protocol.route( - connection, - Collections.emptyMap(), - Collections.emptySet(), - "neo4j", - null, - handler, - mock(Clock.class), - NoopLoggingProvider.INSTANCE, - valueFactory) - .toCompletableFuture() - .join(); - - var summary = routeFuture.join(); - assertEquals(summary.clusterComposition().expirationTimestamp(), TimeUnit.SECONDS.toMillis(1000)); - assertEquals(summary.clusterComposition().routers().size(), 1); - assertEquals(summary.clusterComposition().writers().size(), 1); - assertEquals(summary.clusterComposition().readers().size(), 1); - } - - @Test - void shouldBeginTransactionWithoutBookmark() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarks() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx100"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarksAndConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx4242"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldCommitTransaction() { - var bookmarkString = "neo4j:bookmark:v1:tx4242"; - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var commitHandler = (CommitTxResponseHandler) invocation.getArgument(1); - commitHandler.onSuccess(Map.of("bookmark", value(bookmarkString))); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.commitTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(CommitMessage.COMMIT), any(CommitTxResponseHandler.class)); - then(handler).should().onSummary(bookmarkString); - } - - @Test - void shouldRollbackTransaction() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var rollbackHandler = (RollbackTxResponseHandler) invocation.getArgument(1); - rollbackHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.rollbackTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(RollbackMessage.ROLLBACK), any(RollbackTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx65"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse(Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx163"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInUnmanagedTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(false, null, Collections.emptyMap(), mode); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForSuccessRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(true); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForFailureRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(false); - } - - @Test - void databaseNameInBeginTransaction() { - testDatabaseNameSupport(false); - } - - @Test - void databaseNameForAutoCommitTransactions() { - testDatabaseNameSupport(true); - } - - @Test - void shouldSupportDatabaseNameInBeginTransaction() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.beginTransaction( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldNotSupportDatabaseNameForAutoCommitTransactions() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.runAuto( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldReturnFailedStageWithNoConnectionInteractionsOnTelemetry() { - var connection = mock(Connection.class); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var future = protocol.telemetry(connection, 1, handler).toCompletableFuture(); - - assertTrue(future.isCompletedExceptionally()); - then(connection).shouldHaveNoInteractions(); - } - - private Class expectedMessageFormatType() { - return MessageFormatV43.class; - } - - private void testFailedRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onFailure(error); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onError(error); - } - - private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedRunStage = CompletableFuture.completedStage(null); - var expectedPullStage = CompletableFuture.completedStage(null); - var newBookmarkValue = "neo4j:bookmark:v1:tx98765"; - given(connection.write(any(), any())) - .willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedRunStage; - }) - .willAnswer((Answer>) invocation -> { - var pullHandler = (PullResponseHandlerImpl) invocation.getArgument(1); - pullHandler.onSuccess(Map.of("has_more", value(false), "bookmark", value(newBookmarkValue))); - return expectedPullStage; - }); - @SuppressWarnings("unchecked") - var runHandler = (MessageHandler) mock(MessageHandler.class); - var pullHandler = mock(PullMessageHandler.class); - - var runStage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - runHandler, - NoopLoggingProvider.INSTANCE, - valueFactory); - var pullStage = protocol.pull(connection, 0, UNLIMITED_FETCH_SIZE, pullHandler, valueFactory); - - assertEquals(expectedRunStage, runStage); - assertEquals(expectedPullStage, pullStage); - var runMessage = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(runMessage), any(RunResponseHandler.class)); - var pullMessage = new PullMessage(UNLIMITED_FETCH_SIZE, 0L, valueFactory); - then(connection).should().write(eq(pullMessage), any(PullResponseHandlerImpl.class)); - then(runHandler).should().onSummary(any()); - then(pullHandler) - .should() - .onSummary(new PullResponseHandlerImpl.PullSummaryImpl( - false, Map.of("has_more", value(false), "bookmark", value(newBookmarkValue)))); - } - - private void testRunInUnmanagedTransactionAndWaitForRunResponse(boolean success) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - if (success) { - runHandler.onSuccess(emptyMap()); - } else { - runHandler.onFailure(error); - } - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - if (success) { - then(handler).should().onSummary(any()); - } else { - then(handler).should().onError(error); - } - } - - private void testRunAndWaitForRunResponse( - boolean autoCommitTx, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var initialBookmarks = Collections.singleton("neo4j:bookmark:v1:tx987"); - - if (autoCommitTx) { - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - initialBookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - initialBookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private void testDatabaseNameSupport(boolean autoCommitTx) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - if (autoCommitTx) { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private static Value value(Object value) { - return valueFactory.value(value); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v43/MessageFormatV43Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v43/MessageFormatV43Test.java deleted file mode 100644 index d053f2b854..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v43/MessageFormatV43Test.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v43; - -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.mockito.Mockito.mock; - -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonMessageReader; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -/** - * The MessageFormat under tests is the one provided by the {@link BoltProtocolV43} and not an specific class implementation. - *

- * It's done on this way to make easy to replace the implementation and still getting the same behaviour. - */ -class MessageFormatV43Test { - private static final MessageFormat format = BoltProtocolV43.INSTANCE.createMessageFormat(); - - @Test - void shouldCreateCorrectWriter() { - var writer = format.newWriter(mock(PackOutput.class), mock(ValueFactory.class)); - - assertInstanceOf(MessageWriterV43.class, writer); - } - - @Test - void shouldCreateCorrectReader() { - var reader = format.newReader(mock(PackInput.class), mock(ValueFactory.class)); - - assertInstanceOf(CommonMessageReader.class, reader); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v43/MessageReaderV43Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v43/MessageReaderV43Test.java deleted file mode 100644 index 639ddfb22e..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v43/MessageReaderV43Test.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v43; - -import static java.util.Arrays.asList; -import static java.util.Calendar.APRIL; -import static java.util.Calendar.AUGUST; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.HashMap; -import java.util.List; -import java.util.stream.Stream; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.FailureMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.IgnoredMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.RecordMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.SuccessMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v42.BoltProtocolV42; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.AbstractMessageReaderTestBase; - -/** - * The MessageReader under tests is the one provided by the {@link BoltProtocolV43} and not an specific class implementation. - *

- * It's done on this way to make easy to replace the implementation and still getting the same behaviour. - */ -public class MessageReaderV43Test extends AbstractMessageReaderTestBase { - - @Override - protected Stream supportedMessages() { - return Stream.of( - // V2 Record types - record(valueFactory.point(42, 120.65, -99.2)), - record(valueFactory.point(42, 85.391, 98.8, 11.1)), - record(valueFactory.value(LocalDate.of(2012, AUGUST, 3))), - record(valueFactory.value(OffsetTime.of(23, 59, 59, 999, ZoneOffset.MAX))), - record(valueFactory.value(LocalTime.of(12, 25))), - record(valueFactory.value(LocalDateTime.of(1999, APRIL, 3, 19, 5, 5, 100_200_300))), - record(valueFactory.value( - ZonedDateTime.of(1823, 1, 12, 23, 59, 59, 999_999_999, ZoneOffset.ofHoursMinutes(-7, -15)))), - record(valueFactory.value( - ZonedDateTime.of(1823, 1, 12, 23, 59, 59, 999_999_999, ZoneId.of("Europe/Stockholm")))), - record(valueFactory.isoDuration( - Long.MAX_VALUE - 1, Integer.MAX_VALUE - 1, Short.MAX_VALUE - 1, Byte.MAX_VALUE - 1)), - record(valueFactory.isoDuration(17, 22, 99, 15)), - - // Bolt previous versions valid messages - new FailureMessage("Hello", "World!"), - IgnoredMessage.IGNORED, - new SuccessMessage(new HashMap<>()), - record(valueFactory.value(1337L)), - record(valueFactory.value(List.of("cat", valueFactory.value(null), "dog", valueFactory.value(null)))), - record(valueFactory.value(List.of("k", valueFactory.value(12), "a", valueFactory.value("banana")))), - record(valueFactory.value(asList( - valueFactory.value("k"), - valueFactory.value(12), - valueFactory.value("a"), - valueFactory.value("banana")))), - - // V3 Record Types - record(valueFactory.emptyNodeValue()), - record(valueFactory.filledNodeValue()), - record(valueFactory.emptyRelationshipValue()), - record(valueFactory.filledRelationshipValue()), - record(valueFactory.filledPathValue()), - record(valueFactory.emptyPathValue())); - } - - @Override - protected Stream unsupportedMessages() { - return Stream.of(DiscardAllMessage.DISCARD_ALL); - } - - @Override - protected MessageFormat.Reader newReader(PackInput input) { - return BoltProtocolV42.INSTANCE.createMessageFormat().newReader(input, valueFactory); - } - - private Message record(Value value) { - return new RecordMessage(new Value[] {value}); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v43/MessageWriterV43Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v43/MessageWriterV43Test.java deleted file mode 100644 index a96aac5253..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v43/MessageWriterV43Test.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v43; - -import static java.time.Duration.ofSeconds; -import static java.util.Calendar.DECEMBER; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.neo4j.driver.internal.bolt.api.AccessMode.READ; -import static org.neo4j.driver.internal.bolt.api.AccessMode.WRITE; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage.COMMIT; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage.DISCARD_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage.GOODBYE; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullAllMessage.PULL_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage.RESET; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage.ROLLBACK; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.BoltAgentUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RouteMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.AbstractMessageWriterTestBase; - -/** - * The MessageWriter under tests is the one provided by the {@link BoltProtocolV43} and not an specific class - * implementation. - *

- * It's done on this way to make easy to replace the implementation and still getting the same behaviour. - */ -class MessageWriterV43Test extends AbstractMessageWriterTestBase { - @Override - protected MessageFormat.Writer newWriter(PackOutput output) { - return BoltProtocolV43.INSTANCE.createMessageFormat().newWriter(output, valueFactory); - } - - @Override - protected Stream supportedMessages() { - return Stream.of( - // Bolt V2 Data Types - unmanagedTxRunMessage("RETURN $point", singletonMap("point", valueFactory.point(42, 12.99, -180.0))), - unmanagedTxRunMessage( - "RETURN $point", singletonMap("point", valueFactory.point(42, 0.51, 2.99, 100.123))), - unmanagedTxRunMessage( - "RETURN $date", singletonMap("date", valueFactory.value(LocalDate.ofEpochDay(2147483650L)))), - unmanagedTxRunMessage( - "RETURN $time", - singletonMap("time", valueFactory.value(OffsetTime.of(4, 16, 20, 999, ZoneOffset.MIN)))), - unmanagedTxRunMessage( - "RETURN $time", singletonMap("time", valueFactory.value(LocalTime.of(12, 9, 18, 999_888)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", valueFactory.value(LocalDateTime.of(2049, DECEMBER, 12, 17, 25, 49, 199)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value(ZonedDateTime.of( - 2000, 1, 10, 12, 2, 49, 300, ZoneOffset.ofHoursMinutes(9, 30))))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value( - ZonedDateTime.of(2000, 1, 10, 12, 2, 49, 300, ZoneId.of("Europe/Stockholm"))))), - - // New Bolt V4 messages - new PullMessage(100, 200, valueFactory), - new DiscardMessage(300, 400, valueFactory), - - // Bolt V3 messages - new HelloMessage( - "MyDriver/1.2.3", - BoltAgentUtil.VALUE, - Map.of( - "scheme", - valueFactory.value("basic"), - "principal", - valueFactory.value("neo4j"), - "credentials", - valueFactory.value("neo4j")), - Collections.emptyMap(), - false, - null, - false, - valueFactory), - GOODBYE, - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - READ, - defaultDatabase(), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - WRITE, - database("foo"), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - COMMIT, - ROLLBACK, - RESET, - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - defaultDatabase(), - READ, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - database("foo"), - WRITE, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN 1", Collections.emptyMap()), - - // Bolt V3 messages with struct values - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - defaultDatabase(), - READ, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - database("foo"), - WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN $x", singletonMap("x", valueFactory.point(42, 1, 2, 3))), - - // New 4.3 Messages - routeMessage()); - } - - @Override - protected Stream unsupportedMessages() { - return Stream.of( - // Bolt V1, V2 and V3 messages - PULL_ALL, DISCARD_ALL); - } - - private RouteMessage routeMessage() { - Map routeContext = new HashMap<>(); - routeContext.put("someContext", valueFactory.value(124)); - return new RouteMessage(routeContext, Collections.emptySet(), "dbName", null); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v44/BoltProtocolV44Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v44/BoltProtocolV44Test.java deleted file mode 100644 index 437089a7c8..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v44/BoltProtocolV44Test.java +++ /dev/null @@ -1,768 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v44; - -import static java.time.Duration.ofSeconds; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import io.netty.channel.embedded.EmbeddedChannel; -import java.time.Clock; -import java.time.Duration; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.mockito.stubbing.Answer; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.GqlErrorUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.BeginTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.CommitTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.PullResponseHandlerImpl; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RollbackTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RunResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.PullMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public class BoltProtocolV44Test { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private static final String query = "RETURN $x"; - private static final Map query_params = singletonMap("x", value(42)); - private static final long UNLIMITED_FETCH_SIZE = -1; - private static final Duration txTimeout = ofSeconds(12); - private static final Map txMetadata = singletonMap("x", value(42)); - - protected final BoltProtocol protocol = createProtocol(); - private final EmbeddedChannel channel = new EmbeddedChannel(); - private final InboundMessageDispatcher messageDispatcher = - new InboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE); - - @SuppressWarnings("SameReturnValue") - protected BoltProtocol createProtocol() { - return BoltProtocolV44.INSTANCE; - } - - @BeforeEach - void beforeEach() { - ChannelAttributes.setMessageDispatcher(channel, messageDispatcher); - } - - @AfterEach - void afterEach() { - channel.finishAndReleaseAll(); - } - - @Test - void shouldCreateMessageFormat() { - assertInstanceOf(expectedMessageFormatType(), protocol.createMessageFormat()); - } - - @Test - void shouldInitializeChannel() { - var clock = mock(Clock.class); - var time = 1L; - when(clock.millis()).thenReturn(time); - - var latestAuthMillisFuture = new CompletableFuture(); - - var future = protocol.initializeChannel( - channel, - "MyDriver/0.0.1", - null, - Collections.emptyMap(), - RoutingContext.EMPTY, - null, - clock, - latestAuthMillisFuture, - valueFactory) - .toCompletableFuture(); - - assertEquals(1, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertEquals(1, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - var metadata = Map.of( - "server", value("Neo4j/3.5.0"), - "connection_id", value("bolt-42")); - - messageDispatcher.handleSuccessMessage(metadata); - - assertTrue(future.isDone()); - assertEquals(channel, future.join()); - verify(clock).millis(); - assertTrue(latestAuthMillisFuture.isDone()); - assertEquals(time, latestAuthMillisFuture.join()); - } - - @Test - void shouldFailToInitializeChannelWhenErrorIsReceived() { - var future = protocol.initializeChannel( - channel, - "MyDriver/2.2.1", - null, - Collections.emptyMap(), - RoutingContext.EMPTY, - null, - mock(Clock.class), - new CompletableFuture<>(), - valueFactory) - .toCompletableFuture(); - - assertEquals(1, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertEquals(1, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - messageDispatcher.handleFailureMessage( - GqlErrorUtil.gqlError("Neo.TransientError.General.DatabaseUnavailable", "Error!")); - - assertTrue(future.isDone()); - assertTrue(future.isCompletedExceptionally()); - } - - @Test - void shouldBeginTransactionWithoutBookmark() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarks() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx100"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldCommitTransaction() { - var bookmarkString = "neo4j:bookmark:v1:tx4242"; - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var commitHandler = (CommitTxResponseHandler) invocation.getArgument(1); - commitHandler.onSuccess(Map.of("bookmark", value(bookmarkString))); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.commitTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(CommitMessage.COMMIT), any(CommitTxResponseHandler.class)); - then(handler).should().onSummary(bookmarkString); - } - - @Test - void shouldRollbackTransaction() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var rollbackHandler = (RollbackTxResponseHandler) invocation.getArgument(1); - rollbackHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.rollbackTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(RollbackMessage.ROLLBACK), any(RollbackTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx65"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse(Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx163"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInUnmanagedTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(false, null, Collections.emptyMap(), mode); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForSuccessRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(true); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForFailureRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(false); - } - - @Test - void databaseNameInBeginTransaction() { - testDatabaseNameSupport(false); - } - - @Test - void databaseNameForAutoCommitTransactions() { - testDatabaseNameSupport(true); - } - - @Test - void shouldSupportDatabaseNameInBeginTransaction() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.beginTransaction( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldNotSupportDatabaseNameForAutoCommitTransactions() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.runAuto( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldReturnFailedStageWithNoConnectionInteractionsOnTelemetry() { - var connection = mock(Connection.class); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var future = protocol.telemetry(connection, 1, handler).toCompletableFuture(); - - assertTrue(future.isCompletedExceptionally()); - then(connection).shouldHaveNoInteractions(); - } - - private Class expectedMessageFormatType() { - return MessageFormatV44.class; - } - - private void testFailedRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onFailure(error); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onError(error); - } - - private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedRunStage = CompletableFuture.completedStage(null); - var expectedPullStage = CompletableFuture.completedStage(null); - var newBookmarkValue = "neo4j:bookmark:v1:tx98765"; - given(connection.write(any(), any())) - .willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedRunStage; - }) - .willAnswer((Answer>) invocation -> { - var pullHandler = (PullResponseHandlerImpl) invocation.getArgument(1); - pullHandler.onSuccess(Map.of("has_more", value(false), "bookmark", value(newBookmarkValue))); - return expectedPullStage; - }); - @SuppressWarnings("unchecked") - var runHandler = (MessageHandler) mock(MessageHandler.class); - var pullHandler = mock(PullMessageHandler.class); - - var runStage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - runHandler, - NoopLoggingProvider.INSTANCE, - valueFactory); - var pullStage = protocol.pull(connection, 0, UNLIMITED_FETCH_SIZE, pullHandler, valueFactory); - - assertEquals(expectedRunStage, runStage); - assertEquals(expectedPullStage, pullStage); - var runMessage = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(runMessage), any(RunResponseHandler.class)); - var pullMessage = new PullMessage(UNLIMITED_FETCH_SIZE, 0L, valueFactory); - then(connection).should().write(eq(pullMessage), any(PullResponseHandlerImpl.class)); - then(runHandler).should().onSummary(any()); - then(pullHandler) - .should() - .onSummary(new PullResponseHandlerImpl.PullSummaryImpl( - false, Map.of("has_more", value(false), "bookmark", value(newBookmarkValue)))); - } - - protected void testRunInUnmanagedTransactionAndWaitForRunResponse(boolean success) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - if (success) { - runHandler.onSuccess(emptyMap()); - } else { - runHandler.onFailure(error); - } - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - if (success) { - then(handler).should().onSummary(any()); - } else { - then(handler).should().onError(error); - } - } - - protected void testRunAndWaitForRunResponse( - boolean autoCommitTx, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var initialBookmarks = Collections.singleton("neo4j:bookmark:v1:tx987"); - - if (autoCommitTx) { - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - initialBookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - initialBookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private void testDatabaseNameSupport(boolean autoCommitTx) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - if (autoCommitTx) { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private static Value value(Object value) { - return valueFactory.value(value); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v44/MessageFormatV44Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v44/MessageFormatV44Test.java deleted file mode 100644 index 8e7dab7e89..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v44/MessageFormatV44Test.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v44; - -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.mockito.Mockito.mock; - -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonMessageReader; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -public class MessageFormatV44Test { - private static final MessageFormat format = BoltProtocolV44.INSTANCE.createMessageFormat(); - - @Test - void shouldCreateCorrectWriter() { - var writer = format.newWriter(mock(PackOutput.class), mock(ValueFactory.class)); - - assertInstanceOf(MessageWriterV44.class, writer); - } - - @Test - void shouldCreateCorrectReader() { - var reader = format.newReader(mock(PackInput.class), mock(ValueFactory.class)); - - assertInstanceOf(CommonMessageReader.class, reader); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v44/MessageReaderV44Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v44/MessageReaderV44Test.java deleted file mode 100644 index 4e6898a3e6..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v44/MessageReaderV44Test.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v44; - -import static java.util.Arrays.asList; -import static java.util.Calendar.APRIL; -import static java.util.Calendar.AUGUST; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.HashMap; -import java.util.List; -import java.util.stream.Stream; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.FailureMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.IgnoredMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.RecordMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.SuccessMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.AbstractMessageReaderTestBase; - -/** - * The MessageReader under tests is the one provided by the {@link BoltProtocolV44} and not a specific class implementation. - *

- * It's done on this way to make easy to replace the implementation and still getting the same behaviour. - */ -public class MessageReaderV44Test extends AbstractMessageReaderTestBase { - @Override - protected Stream supportedMessages() { - return Stream.of( - // V2 Record types - record(valueFactory.point(42, 120.65, -99.2)), - record(valueFactory.point(42, 85.391, 98.8, 11.1)), - record(valueFactory.value(LocalDate.of(2012, AUGUST, 3))), - record(valueFactory.value(OffsetTime.of(23, 59, 59, 999, ZoneOffset.MAX))), - record(valueFactory.value(LocalTime.of(12, 25))), - record(valueFactory.value(LocalDateTime.of(1999, APRIL, 3, 19, 5, 5, 100_200_300))), - record(valueFactory.value( - ZonedDateTime.of(1823, 1, 12, 23, 59, 59, 999_999_999, ZoneOffset.ofHoursMinutes(-7, -15)))), - record(valueFactory.value( - ZonedDateTime.of(1823, 1, 12, 23, 59, 59, 999_999_999, ZoneId.of("Europe/Stockholm")))), - record(valueFactory.isoDuration( - Long.MAX_VALUE - 1, Integer.MAX_VALUE - 1, Short.MAX_VALUE - 1, Byte.MAX_VALUE - 1)), - record(valueFactory.isoDuration(17, 22, 99, 15)), - - // Bolt previous versions valid messages - new FailureMessage("Hello", "World!"), - IgnoredMessage.IGNORED, - new SuccessMessage(new HashMap<>()), - record(valueFactory.value(1337L)), - record(valueFactory.value(List.of("cat", valueFactory.value(null), "dog", valueFactory.value(null)))), - record(valueFactory.value(List.of("k", valueFactory.value(12), "a", valueFactory.value("banana")))), - record(valueFactory.value(asList( - valueFactory.value("k"), - valueFactory.value(12), - valueFactory.value("a"), - valueFactory.value("banana")))), - - // V3 Record Types - record(valueFactory.emptyNodeValue()), - record(valueFactory.filledNodeValue()), - record(valueFactory.emptyRelationshipValue()), - record(valueFactory.filledRelationshipValue()), - record(valueFactory.filledPathValue()), - record(valueFactory.emptyPathValue())); - } - - @Override - protected Stream unsupportedMessages() { - return Stream.of(DiscardAllMessage.DISCARD_ALL); - } - - @Override - protected MessageFormat.Reader newReader(PackInput input) { - return BoltProtocolV44.INSTANCE.createMessageFormat().newReader(input, valueFactory); - } - - private Message record(Value value) { - return new RecordMessage(new Value[] {value}); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v44/MessageWriterV44Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v44/MessageWriterV44Test.java deleted file mode 100644 index 5b8f4ada90..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v44/MessageWriterV44Test.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v44; - -import static java.time.Duration.ofSeconds; -import static java.util.Calendar.DECEMBER; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.neo4j.driver.internal.bolt.api.AccessMode.READ; -import static org.neo4j.driver.internal.bolt.api.AccessMode.WRITE; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage.COMMIT; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage.DISCARD_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage.GOODBYE; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullAllMessage.PULL_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage.RESET; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage.ROLLBACK; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.BoltAgentUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RouteMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.AbstractMessageWriterTestBase; - -/** - * The MessageWriter under tests is the one provided by the {@link BoltProtocolV44} and not a specific class - * implementation. - *

- * It's done on this way to make easy to replace the implementation and still getting the same behaviour. - */ -public class MessageWriterV44Test extends AbstractMessageWriterTestBase { - @Override - protected MessageFormat.Writer newWriter(PackOutput output) { - return BoltProtocolV44.INSTANCE.createMessageFormat().newWriter(output, valueFactory); - } - - @Override - protected Stream supportedMessages() { - return Stream.of( - // Bolt V2 Data Types - unmanagedTxRunMessage("RETURN $point", singletonMap("point", valueFactory.point(42, 12.99, -180.0))), - unmanagedTxRunMessage( - "RETURN $point", singletonMap("point", valueFactory.point(42, 0.51, 2.99, 100.123))), - unmanagedTxRunMessage( - "RETURN $date", singletonMap("date", valueFactory.value(LocalDate.ofEpochDay(2147483650L)))), - unmanagedTxRunMessage( - "RETURN $time", - singletonMap("time", valueFactory.value(OffsetTime.of(4, 16, 20, 999, ZoneOffset.MIN)))), - unmanagedTxRunMessage( - "RETURN $time", singletonMap("time", valueFactory.value(LocalTime.of(12, 9, 18, 999_888)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", valueFactory.value(LocalDateTime.of(2049, DECEMBER, 12, 17, 25, 49, 199)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value(ZonedDateTime.of( - 2000, 1, 10, 12, 2, 49, 300, ZoneOffset.ofHoursMinutes(9, 30))))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value( - ZonedDateTime.of(2000, 1, 10, 12, 2, 49, 300, ZoneId.of("Europe/Stockholm"))))), - - // New Bolt V4 messages - new PullMessage(100, 200, valueFactory), - new DiscardMessage(300, 400, valueFactory), - - // Bolt V3 messages - new HelloMessage( - "MyDriver/1.2.3", - BoltAgentUtil.VALUE, - Map.of( - "scheme", - valueFactory.value("basic"), - "principal", - valueFactory.value("neo4j"), - "credentials", - valueFactory.value("neo4j")), - Collections.emptyMap(), - false, - null, - false, - valueFactory), - GOODBYE, - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - READ, - defaultDatabase(), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - WRITE, - database("foo"), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - COMMIT, - ROLLBACK, - RESET, - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - defaultDatabase(), - READ, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - database("foo"), - WRITE, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN 1", Collections.emptyMap()), - - // Bolt V3 messages with struct values - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - defaultDatabase(), - READ, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - database("foo"), - WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN $x", singletonMap("x", valueFactory.point(42, 1, 2, 3))), - - // New 4.3 Messages - routeMessage()); - } - - @Override - protected Stream unsupportedMessages() { - return Stream.of( - // Bolt V1, V2 and V3 messages - PULL_ALL, DISCARD_ALL); - } - - private RouteMessage routeMessage() { - Map routeContext = new HashMap<>(); - routeContext.put("someContext", valueFactory.value(124)); - return new RouteMessage(routeContext, Collections.emptySet(), "dbName", null); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/BoltProtocolV5Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/BoltProtocolV5Test.java deleted file mode 100644 index e40ee3047f..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/BoltProtocolV5Test.java +++ /dev/null @@ -1,813 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v5; - -import static java.time.Duration.ofSeconds; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import io.netty.channel.embedded.EmbeddedChannel; -import java.time.Clock; -import java.time.Duration; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.mockito.stubbing.Answer; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.GqlErrorUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.BeginTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.CommitTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.PullResponseHandlerImpl; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RollbackTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RunResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.PullMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public class BoltProtocolV5Test { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - protected static final String query = "RETURN $x"; - protected static final Map query_params = singletonMap("x", value(42)); - private static final long UNLIMITED_FETCH_SIZE = -1; - private static final Duration txTimeout = ofSeconds(12); - private static final Map txMetadata = singletonMap("x", value(42)); - - protected final BoltProtocol protocol = createProtocol(); - private final EmbeddedChannel channel = new EmbeddedChannel(); - private final InboundMessageDispatcher messageDispatcher = - new InboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE); - - @SuppressWarnings("SameReturnValue") - protected BoltProtocol createProtocol() { - return BoltProtocolV5.INSTANCE; - } - - @BeforeEach - void beforeEach() { - ChannelAttributes.setMessageDispatcher(channel, messageDispatcher); - } - - @AfterEach - void afterEach() { - channel.finishAndReleaseAll(); - } - - @Test - void shouldCreateMessageFormat() { - assertInstanceOf(expectedMessageFormatType(), protocol.createMessageFormat()); - } - - @Test - void shouldInitializeChannel() { - var clock = mock(Clock.class); - var time = 1L; - when(clock.millis()).thenReturn(time); - - var latestAuthMillisFuture = new CompletableFuture(); - - var future = protocol.initializeChannel( - channel, - "MyDriver/0.0.1", - null, - Collections.emptyMap(), - RoutingContext.EMPTY, - null, - clock, - latestAuthMillisFuture, - valueFactory) - .toCompletableFuture(); - - assertEquals(1, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertEquals(1, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - var metadata = Map.of( - "server", value("Neo4j/3.5.0"), - "connection_id", value("bolt-42")); - - messageDispatcher.handleSuccessMessage(metadata); - - assertTrue(future.isDone()); - assertEquals(channel, future.join()); - verify(clock).millis(); - assertTrue(latestAuthMillisFuture.isDone()); - assertEquals(time, latestAuthMillisFuture.join()); - } - - @Test - void shouldFailToInitializeChannelWhenErrorIsReceived() { - var future = protocol.initializeChannel( - channel, - "MyDriver/2.2.1", - null, - Collections.emptyMap(), - RoutingContext.EMPTY, - null, - mock(Clock.class), - new CompletableFuture<>(), - valueFactory) - .toCompletableFuture(); - - assertEquals(1, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertEquals(1, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - messageDispatcher.handleFailureMessage( - GqlErrorUtil.gqlError("Neo.TransientError.General.DatabaseUnavailable", "Error!")); - - assertTrue(future.isDone()); - assertTrue(future.isCompletedExceptionally()); - } - - @Test - void shouldBeginTransactionWithoutBookmark() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarks() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx100"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarksAndConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx4242"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldCommitTransaction() { - var bookmarkString = "neo4j:bookmark:v1:tx4242"; - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var commitHandler = (CommitTxResponseHandler) invocation.getArgument(1); - commitHandler.onSuccess(Map.of("bookmark", value(bookmarkString))); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.commitTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(CommitMessage.COMMIT), any(CommitTxResponseHandler.class)); - then(handler).should().onSummary(bookmarkString); - } - - @Test - void shouldRollbackTransaction() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var rollbackHandler = (RollbackTxResponseHandler) invocation.getArgument(1); - rollbackHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.rollbackTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(RollbackMessage.ROLLBACK), any(RollbackTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx65"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse(Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx163"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInUnmanagedTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(false, null, Collections.emptyMap(), mode); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForSuccessRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(true); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForFailureRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(false); - } - - @Test - void databaseNameInBeginTransaction() { - testDatabaseNameSupport(false); - } - - @Test - void databaseNameForAutoCommitTransactions() { - testDatabaseNameSupport(true); - } - - @Test - void shouldSupportDatabaseNameInBeginTransaction() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.beginTransaction( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldNotSupportDatabaseNameForAutoCommitTransactions() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.runAuto( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldReturnFailedStageWithNoConnectionInteractionsOnTelemetry() { - var connection = mock(Connection.class); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var future = protocol.telemetry(connection, 1, handler).toCompletableFuture(); - - assertTrue(future.isCompletedExceptionally()); - then(connection).shouldHaveNoInteractions(); - } - - private Class expectedMessageFormatType() { - return MessageFormatV5.class; - } - - private void testFailedRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onFailure(error); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onError(error); - } - - private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedRunStage = CompletableFuture.completedStage(null); - var expectedPullStage = CompletableFuture.completedStage(null); - var newBookmarkValue = "neo4j:bookmark:v1:tx98765"; - given(connection.write(any(), any())) - .willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedRunStage; - }) - .willAnswer((Answer>) invocation -> { - var pullHandler = (PullResponseHandlerImpl) invocation.getArgument(1); - pullHandler.onSuccess(Map.of("has_more", value(false), "bookmark", value(newBookmarkValue))); - return expectedPullStage; - }); - @SuppressWarnings("unchecked") - var runHandler = (MessageHandler) mock(MessageHandler.class); - var pullHandler = mock(PullMessageHandler.class); - - var runStage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - runHandler, - NoopLoggingProvider.INSTANCE, - valueFactory); - var pullStage = protocol.pull(connection, 0, UNLIMITED_FETCH_SIZE, pullHandler, valueFactory); - - assertEquals(expectedRunStage, runStage); - assertEquals(expectedPullStage, pullStage); - var runMessage = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(runMessage), any(RunResponseHandler.class)); - var pullMessage = new PullMessage(UNLIMITED_FETCH_SIZE, 0L, valueFactory); - then(connection).should().write(eq(pullMessage), any(PullResponseHandlerImpl.class)); - then(runHandler).should().onSummary(any()); - then(pullHandler) - .should() - .onSummary(new PullResponseHandlerImpl.PullSummaryImpl( - false, Map.of("has_more", value(false), "bookmark", value(newBookmarkValue)))); - } - - protected void testRunInUnmanagedTransactionAndWaitForRunResponse(boolean success) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - if (success) { - runHandler.onSuccess(emptyMap()); - } else { - runHandler.onFailure(error); - } - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - if (success) { - then(handler).should().onSummary(any()); - } else { - then(handler).should().onError(error); - } - } - - protected void testRunAndWaitForRunResponse( - boolean autoCommitTx, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var initialBookmarks = Collections.singleton("neo4j:bookmark:v1:tx987"); - - if (autoCommitTx) { - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - initialBookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - initialBookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private void testDatabaseNameSupport(boolean autoCommitTx) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - if (autoCommitTx) { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private static Value value(Object value) { - return valueFactory.value(value); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/MessageFormatV5Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/MessageFormatV5Test.java deleted file mode 100644 index e221749fc3..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/MessageFormatV5Test.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v5; - -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.mockito.Mockito.mock; - -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -public class MessageFormatV5Test { - private static final MessageFormat format = BoltProtocolV5.INSTANCE.createMessageFormat(); - - @Test - void shouldCreateCorrectWriter() { - var writer = format.newWriter(mock(PackOutput.class), mock(ValueFactory.class)); - - assertInstanceOf(MessageWriterV5.class, writer); - } - - @Test - void shouldCreateCorrectReader() { - var reader = format.newReader(mock(PackInput.class), mock(ValueFactory.class)); - - assertInstanceOf(MessageReaderV5.class, reader); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/MessageReaderV5Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/MessageReaderV5Test.java deleted file mode 100644 index 2019f2dace..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/MessageReaderV5Test.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v5; - -import static java.util.Arrays.asList; -import static java.util.Calendar.APRIL; -import static java.util.Calendar.AUGUST; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.HashMap; -import java.util.List; -import java.util.stream.Stream; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.FailureMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.IgnoredMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.RecordMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.SuccessMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.AbstractMessageReaderTestBase; - -/** - * The MessageReader under tests is the one provided by the {@link BoltProtocolV5} and not a specific class implementation. - *

- * It's done on this way to make easy to replace the implementation and still getting the same behaviour. - */ -public class MessageReaderV5Test extends AbstractMessageReaderTestBase { - @Override - protected Stream supportedMessages() { - return Stream.of( - // V2 Record types - record(valueFactory.point(42, 120.65, -99.2)), - record(valueFactory.point(42, 85.391, 98.8, 11.1)), - record(valueFactory.value(LocalDate.of(2012, AUGUST, 3))), - record(valueFactory.value(OffsetTime.of(23, 59, 59, 999, ZoneOffset.MAX))), - record(valueFactory.value(LocalTime.of(12, 25))), - record(valueFactory.value(LocalDateTime.of(1999, APRIL, 3, 19, 5, 5, 100_200_300))), - record(valueFactory.value( - ZonedDateTime.of(1823, 1, 12, 23, 59, 59, 999_999_999, ZoneOffset.ofHoursMinutes(-7, -15)))), - record(valueFactory.value( - ZonedDateTime.of(1823, 1, 12, 23, 59, 59, 999_999_999, ZoneId.of("Europe/Stockholm")))), - record(valueFactory.isoDuration( - Long.MAX_VALUE - 1, Integer.MAX_VALUE - 1, Short.MAX_VALUE - 1, Byte.MAX_VALUE - 1)), - record(valueFactory.isoDuration(17, 22, 99, 15)), - - // Bolt previous versions valid messages - new FailureMessage("Hello", "World!"), - IgnoredMessage.IGNORED, - new SuccessMessage(new HashMap<>()), - record(valueFactory.value(1337L)), - record(valueFactory.value(List.of("cat", valueFactory.value(null), "dog", valueFactory.value(null)))), - record(valueFactory.value(List.of("k", valueFactory.value(12), "a", valueFactory.value("banana")))), - record(valueFactory.value(asList( - valueFactory.value("k"), - valueFactory.value(12), - valueFactory.value("a"), - valueFactory.value("banana")))), - - // V3 Record Types - record(valueFactory.emptyNodeValue()), - record(valueFactory.filledNodeValue()), - record(valueFactory.emptyRelationshipValue()), - record(valueFactory.filledRelationshipValue()), - record(valueFactory.filledPathValue()), - record(valueFactory.emptyPathValue())); - } - - @Override - protected Stream unsupportedMessages() { - return Stream.of(DiscardAllMessage.DISCARD_ALL); - } - - @Override - protected MessageFormat.Reader newReader(PackInput input) { - return BoltProtocolV5.INSTANCE.createMessageFormat().newReader(input, valueFactory); - } - - private Message record(Value value) { - return new RecordMessage(new Value[] {value}); - } - - @Override - protected boolean isElementIdEnabled() { - return true; - } - - @Override - protected boolean isDateTimeUtcEnabled() { - return true; - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/MessageWriterV5Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/MessageWriterV5Test.java deleted file mode 100644 index 76a8b168b1..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v5/MessageWriterV5Test.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v5; - -import static java.time.Duration.ofSeconds; -import static java.util.Calendar.DECEMBER; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.neo4j.driver.internal.bolt.api.AccessMode.READ; -import static org.neo4j.driver.internal.bolt.api.AccessMode.WRITE; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage.COMMIT; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage.DISCARD_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage.GOODBYE; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullAllMessage.PULL_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage.RESET; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage.ROLLBACK; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.BoltAgentUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RouteMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.AbstractMessageWriterTestBase; - -/** - * The MessageWriter under tests is the one provided by the {@link BoltProtocolV5} and not a specific class - * implementation. - *

- * It's done on this way to make easy to replace the implementation and still getting the same behaviour. - */ -public class MessageWriterV5Test extends AbstractMessageWriterTestBase { - @Override - protected MessageFormat.Writer newWriter(PackOutput output) { - return BoltProtocolV5.INSTANCE.createMessageFormat().newWriter(output, valueFactory); - } - - @Override - protected Stream supportedMessages() { - return Stream.of( - // Bolt V2 Data Types - unmanagedTxRunMessage("RETURN $point", singletonMap("point", valueFactory.point(42, 12.99, -180.0))), - unmanagedTxRunMessage( - "RETURN $point", singletonMap("point", valueFactory.point(42, 0.51, 2.99, 100.123))), - unmanagedTxRunMessage( - "RETURN $date", singletonMap("date", valueFactory.value(LocalDate.ofEpochDay(2147483650L)))), - unmanagedTxRunMessage( - "RETURN $time", - singletonMap("time", valueFactory.value(OffsetTime.of(4, 16, 20, 999, ZoneOffset.MIN)))), - unmanagedTxRunMessage( - "RETURN $time", singletonMap("time", valueFactory.value(LocalTime.of(12, 9, 18, 999_888)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", valueFactory.value(LocalDateTime.of(2049, DECEMBER, 12, 17, 25, 49, 199)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value(ZonedDateTime.of( - 2000, 1, 10, 12, 2, 49, 300, ZoneOffset.ofHoursMinutes(9, 30))))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value( - ZonedDateTime.of(2000, 1, 10, 12, 2, 49, 300, ZoneId.of("Europe/Stockholm"))))), - - // New Bolt V4 messages - new PullMessage(100, 200, valueFactory), - new DiscardMessage(300, 400, valueFactory), - - // Bolt V3 messages - new HelloMessage( - "MyDriver/1.2.3", - BoltAgentUtil.VALUE, - Map.of( - "scheme", - valueFactory.value("basic"), - "principal", - valueFactory.value("neo4j"), - "credentials", - valueFactory.value("neo4j")), - Collections.emptyMap(), - false, - null, - false, - valueFactory), - GOODBYE, - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - READ, - defaultDatabase(), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - WRITE, - database("foo"), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - COMMIT, - ROLLBACK, - RESET, - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - defaultDatabase(), - READ, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - database("foo"), - WRITE, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN 1", Collections.emptyMap()), - - // Bolt V3 messages with struct values - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - defaultDatabase(), - READ, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - database("foo"), - WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN $x", singletonMap("x", valueFactory.point(42, 1, 2, 3))), - - // New 4.3 Messages - routeMessage()); - } - - @Override - protected Stream unsupportedMessages() { - return Stream.of( - // Bolt V1, V2 and V3 messages - PULL_ALL, DISCARD_ALL); - } - - private RouteMessage routeMessage() { - Map routeContext = new HashMap<>(); - routeContext.put("someContext", valueFactory.value(124)); - return new RouteMessage(routeContext, Collections.emptySet(), "dbName", null); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v51/BoltProtocolV51Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v51/BoltProtocolV51Test.java deleted file mode 100644 index 3c21b29f2d..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v51/BoltProtocolV51Test.java +++ /dev/null @@ -1,789 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v51; - -import static java.time.Duration.ofSeconds; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import io.netty.channel.embedded.EmbeddedChannel; -import java.time.Clock; -import java.time.Duration; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.mockito.stubbing.Answer; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.BeginTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.CommitTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.PullResponseHandlerImpl; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RollbackTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RunResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.PullMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.LogonMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public class BoltProtocolV51Test { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private static final String query = "RETURN $x"; - private static final Map query_params = singletonMap("x", value(42)); - private static final long UNLIMITED_FETCH_SIZE = -1; - private static final Duration txTimeout = ofSeconds(12); - private static final Map txMetadata = singletonMap("x", value(42)); - - protected final BoltProtocol protocol = createProtocol(); - private final EmbeddedChannel channel = new EmbeddedChannel(); - private final InboundMessageDispatcher messageDispatcher = - new InboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE); - - @SuppressWarnings("SameReturnValue") - protected BoltProtocol createProtocol() { - return BoltProtocolV51.INSTANCE; - } - - @BeforeEach - void beforeEach() { - ChannelAttributes.setMessageDispatcher(channel, messageDispatcher); - } - - @AfterEach - void afterEach() { - channel.finishAndReleaseAll(); - } - - @Test - void shouldCreateMessageFormat() { - assertInstanceOf(expectedMessageFormatType(), protocol.createMessageFormat()); - } - - @Test - void shouldInitializeChannel() { - var clock = mock(Clock.class); - var time = 1L; - when(clock.millis()).thenReturn(time); - - var latestAuthMillisFuture = new CompletableFuture(); - - var future = protocol.initializeChannel( - channel, - "MyDriver/0.0.1", - null, - Collections.emptyMap(), - RoutingContext.EMPTY, - null, - clock, - latestAuthMillisFuture, - valueFactory) - .toCompletableFuture(); - - assertEquals(2, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertInstanceOf(LogonMessage.class, channel.outboundMessages().poll()); - assertEquals(2, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - var metadata = Map.of( - "server", value("Neo4j/3.5.0"), - "connection_id", value("bolt-42")); - - messageDispatcher.handleSuccessMessage(metadata); - messageDispatcher.handleSuccessMessage(Collections.emptyMap()); - - assertTrue(future.isDone()); - assertEquals(channel, future.join()); - verify(clock).millis(); - assertTrue(latestAuthMillisFuture.isDone()); - assertEquals(time, latestAuthMillisFuture.join()); - } - - @Test - void shouldBeginTransactionWithoutBookmark() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarks() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx100"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarksAndConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx4242"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldCommitTransaction() { - var bookmarkString = "neo4j:bookmark:v1:tx4242"; - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var commitHandler = (CommitTxResponseHandler) invocation.getArgument(1); - commitHandler.onSuccess(Map.of("bookmark", value(bookmarkString))); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.commitTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(CommitMessage.COMMIT), any(CommitTxResponseHandler.class)); - then(handler).should().onSummary(bookmarkString); - } - - @Test - void shouldRollbackTransaction() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var rollbackHandler = (RollbackTxResponseHandler) invocation.getArgument(1); - rollbackHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.rollbackTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(RollbackMessage.ROLLBACK), any(RollbackTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx65"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse(Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx163"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInUnmanagedTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(false, null, Collections.emptyMap(), mode); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForSuccessRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(true); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForFailureRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(false); - } - - @Test - void databaseNameInBeginTransaction() { - testDatabaseNameSupport(false); - } - - @Test - void databaseNameForAutoCommitTransactions() { - testDatabaseNameSupport(true); - } - - @Test - void shouldSupportDatabaseNameInBeginTransaction() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.beginTransaction( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldNotSupportDatabaseNameForAutoCommitTransactions() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.runAuto( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldReturnFailedStageWithNoConnectionInteractionsOnTelemetry() { - var connection = mock(Connection.class); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var future = protocol.telemetry(connection, 1, handler).toCompletableFuture(); - - assertTrue(future.isCompletedExceptionally()); - then(connection).shouldHaveNoInteractions(); - } - - private Class expectedMessageFormatType() { - return MessageFormatV51.class; - } - - private void testFailedRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onFailure(error); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onError(error); - } - - private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedRunStage = CompletableFuture.completedStage(null); - var expectedPullStage = CompletableFuture.completedStage(null); - var newBookmarkValue = "neo4j:bookmark:v1:tx98765"; - given(connection.write(any(), any())) - .willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedRunStage; - }) - .willAnswer((Answer>) invocation -> { - var pullHandler = (PullResponseHandlerImpl) invocation.getArgument(1); - pullHandler.onSuccess(Map.of("has_more", value(false), "bookmark", value(newBookmarkValue))); - return expectedPullStage; - }); - @SuppressWarnings("unchecked") - var runHandler = (MessageHandler) mock(MessageHandler.class); - var pullHandler = mock(PullMessageHandler.class); - - var runStage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - runHandler, - NoopLoggingProvider.INSTANCE, - valueFactory); - var pullStage = protocol.pull(connection, 0, UNLIMITED_FETCH_SIZE, pullHandler, valueFactory); - - assertEquals(expectedRunStage, runStage); - assertEquals(expectedPullStage, pullStage); - var runMessage = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(runMessage), any(RunResponseHandler.class)); - var pullMessage = new PullMessage(UNLIMITED_FETCH_SIZE, 0L, valueFactory); - then(connection).should().write(eq(pullMessage), any(PullResponseHandlerImpl.class)); - then(runHandler).should().onSummary(any()); - then(pullHandler) - .should() - .onSummary(new PullResponseHandlerImpl.PullSummaryImpl( - false, Map.of("has_more", value(false), "bookmark", value(newBookmarkValue)))); - } - - protected void testRunInUnmanagedTransactionAndWaitForRunResponse(boolean success) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - if (success) { - runHandler.onSuccess(emptyMap()); - } else { - runHandler.onFailure(error); - } - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - if (success) { - then(handler).should().onSummary(any()); - } else { - then(handler).should().onError(error); - } - } - - protected void testRunAndWaitForRunResponse( - boolean autoCommitTx, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var initialBookmarks = Collections.singleton("neo4j:bookmark:v1:tx987"); - - if (autoCommitTx) { - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - initialBookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - initialBookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private void testDatabaseNameSupport(boolean autoCommitTx) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - if (autoCommitTx) { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private static Value value(Object value) { - return valueFactory.value(value); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v51/MessageFormatV51Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v51/MessageFormatV51Test.java deleted file mode 100644 index 133d4c5668..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v51/MessageFormatV51Test.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v51; - -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.mockito.Mockito.mock; - -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v5.MessageReaderV5; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -public class MessageFormatV51Test { - private static final MessageFormat format = BoltProtocolV51.INSTANCE.createMessageFormat(); - - @Test - void shouldCreateCorrectWriter() { - var writer = format.newWriter(mock(PackOutput.class), mock(ValueFactory.class)); - - assertInstanceOf(MessageWriterV51.class, writer); - } - - @Test - void shouldCreateCorrectReader() { - var reader = format.newReader(mock(PackInput.class), mock(ValueFactory.class)); - - assertInstanceOf(MessageReaderV5.class, reader); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v51/MessageWriterV51Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v51/MessageWriterV51Test.java deleted file mode 100644 index 3c037272c1..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v51/MessageWriterV51Test.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v51; - -import static java.time.Duration.ofSeconds; -import static java.util.Calendar.DECEMBER; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.neo4j.driver.internal.bolt.api.AccessMode.READ; -import static org.neo4j.driver.internal.bolt.api.AccessMode.WRITE; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage.COMMIT; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage.DISCARD_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage.GOODBYE; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullAllMessage.PULL_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage.RESET; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage.ROLLBACK; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.BoltAgentUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RouteMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.AbstractMessageWriterTestBase; - -public class MessageWriterV51Test extends AbstractMessageWriterTestBase { - @Override - protected MessageFormat.Writer newWriter(PackOutput output) { - return BoltProtocolV51.INSTANCE.createMessageFormat().newWriter(output, valueFactory); - } - - @Override - protected Stream supportedMessages() { - return Stream.of( - // Bolt V2 Data Types - unmanagedTxRunMessage("RETURN $point", singletonMap("point", valueFactory.point(42, 12.99, -180.0))), - unmanagedTxRunMessage( - "RETURN $point", singletonMap("point", valueFactory.point(42, 0.51, 2.99, 100.123))), - unmanagedTxRunMessage( - "RETURN $date", singletonMap("date", valueFactory.value(LocalDate.ofEpochDay(2147483650L)))), - unmanagedTxRunMessage( - "RETURN $time", - singletonMap("time", valueFactory.value(OffsetTime.of(4, 16, 20, 999, ZoneOffset.MIN)))), - unmanagedTxRunMessage( - "RETURN $time", singletonMap("time", valueFactory.value(LocalTime.of(12, 9, 18, 999_888)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", valueFactory.value(LocalDateTime.of(2049, DECEMBER, 12, 17, 25, 49, 199)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value(ZonedDateTime.of( - 2000, 1, 10, 12, 2, 49, 300, ZoneOffset.ofHoursMinutes(9, 30))))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value( - ZonedDateTime.of(2000, 1, 10, 12, 2, 49, 300, ZoneId.of("Europe/Stockholm"))))), - - // New Bolt V4 messages - new PullMessage(100, 200, valueFactory), - new DiscardMessage(300, 400, valueFactory), - - // Bolt V3 messages - new HelloMessage( - "MyDriver/1.2.3", - BoltAgentUtil.VALUE, - Map.of( - "scheme", - valueFactory.value("basic"), - "principal", - valueFactory.value("neo4j"), - "credentials", - valueFactory.value("neo4j")), - Collections.emptyMap(), - false, - null, - false, - valueFactory), - GOODBYE, - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - READ, - defaultDatabase(), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - WRITE, - database("foo"), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - COMMIT, - ROLLBACK, - RESET, - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - defaultDatabase(), - READ, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - database("foo"), - WRITE, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN 1", Collections.emptyMap()), - - // Bolt V3 messages with struct values - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - defaultDatabase(), - READ, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - database("foo"), - WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN $x", singletonMap("x", valueFactory.point(42, 1, 2, 3))), - - // New 4.3 Messages - routeMessage()); - } - - @Override - protected Stream unsupportedMessages() { - return Stream.of( - // Bolt V1, V2 and V3 messages - PULL_ALL, DISCARD_ALL); - } - - private RouteMessage routeMessage() { - Map routeContext = new HashMap<>(); - routeContext.put("someContext", valueFactory.value(124)); - return new RouteMessage(routeContext, Collections.emptySet(), "dbName", null); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v52/BoltProtocolV52Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v52/BoltProtocolV52Test.java deleted file mode 100644 index d4d466163e..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v52/BoltProtocolV52Test.java +++ /dev/null @@ -1,790 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v52; - -import static java.time.Duration.ofSeconds; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import io.netty.channel.embedded.EmbeddedChannel; -import java.time.Clock; -import java.time.Duration; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.mockito.stubbing.Answer; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.BeginTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.CommitTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.PullResponseHandlerImpl; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RollbackTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RunResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.PullMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.LogonMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v51.MessageFormatV51; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public class BoltProtocolV52Test { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private static final String query = "RETURN $x"; - private static final Map query_params = singletonMap("x", value(42)); - private static final long UNLIMITED_FETCH_SIZE = -1; - private static final Duration txTimeout = ofSeconds(12); - private static final Map txMetadata = singletonMap("x", value(42)); - - protected final BoltProtocol protocol = createProtocol(); - private final EmbeddedChannel channel = new EmbeddedChannel(); - private final InboundMessageDispatcher messageDispatcher = - new InboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE); - - @SuppressWarnings("SameReturnValue") - protected BoltProtocol createProtocol() { - return BoltProtocolV52.INSTANCE; - } - - @BeforeEach - void beforeEach() { - ChannelAttributes.setMessageDispatcher(channel, messageDispatcher); - } - - @AfterEach - void afterEach() { - channel.finishAndReleaseAll(); - } - - @Test - void shouldCreateMessageFormat() { - assertInstanceOf(expectedMessageFormatType(), protocol.createMessageFormat()); - } - - @Test - void shouldInitializeChannel() { - var clock = mock(Clock.class); - var time = 1L; - when(clock.millis()).thenReturn(time); - - var latestAuthMillisFuture = new CompletableFuture(); - - var future = protocol.initializeChannel( - channel, - "MyDriver/0.0.1", - null, - Collections.emptyMap(), - RoutingContext.EMPTY, - null, - clock, - latestAuthMillisFuture, - valueFactory) - .toCompletableFuture(); - - assertEquals(2, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertInstanceOf(LogonMessage.class, channel.outboundMessages().poll()); - assertEquals(2, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - var metadata = Map.of( - "server", value("Neo4j/3.5.0"), - "connection_id", value("bolt-42")); - - messageDispatcher.handleSuccessMessage(metadata); - messageDispatcher.handleSuccessMessage(Collections.emptyMap()); - - assertTrue(future.isDone()); - assertEquals(channel, future.join()); - verify(clock).millis(); - assertTrue(latestAuthMillisFuture.isDone()); - assertEquals(time, latestAuthMillisFuture.join()); - } - - @Test - void shouldBeginTransactionWithoutBookmark() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarks() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx100"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarksAndConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx4242"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldCommitTransaction() { - var bookmarkString = "neo4j:bookmark:v1:tx4242"; - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var commitHandler = (CommitTxResponseHandler) invocation.getArgument(1); - commitHandler.onSuccess(Map.of("bookmark", value(bookmarkString))); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.commitTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(CommitMessage.COMMIT), any(CommitTxResponseHandler.class)); - then(handler).should().onSummary(bookmarkString); - } - - @Test - void shouldRollbackTransaction() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var rollbackHandler = (RollbackTxResponseHandler) invocation.getArgument(1); - rollbackHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.rollbackTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(RollbackMessage.ROLLBACK), any(RollbackTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx65"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse(Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx163"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInUnmanagedTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(false, null, Collections.emptyMap(), mode); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForSuccessRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(true); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForFailureRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(false); - } - - @Test - void databaseNameInBeginTransaction() { - testDatabaseNameSupport(false); - } - - @Test - void databaseNameForAutoCommitTransactions() { - testDatabaseNameSupport(true); - } - - @Test - void shouldSupportDatabaseNameInBeginTransaction() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.beginTransaction( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldNotSupportDatabaseNameForAutoCommitTransactions() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.runAuto( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldReturnFailedStageWithNoConnectionInteractionsOnTelemetry() { - var connection = mock(Connection.class); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var future = protocol.telemetry(connection, 1, handler).toCompletableFuture(); - - assertTrue(future.isCompletedExceptionally()); - then(connection).shouldHaveNoInteractions(); - } - - private Class expectedMessageFormatType() { - return MessageFormatV51.class; - } - - private void testFailedRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onFailure(error); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onError(error); - } - - private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedRunStage = CompletableFuture.completedStage(null); - var expectedPullStage = CompletableFuture.completedStage(null); - var newBookmarkValue = "neo4j:bookmark:v1:tx98765"; - given(connection.write(any(), any())) - .willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedRunStage; - }) - .willAnswer((Answer>) invocation -> { - var pullHandler = (PullResponseHandlerImpl) invocation.getArgument(1); - pullHandler.onSuccess(Map.of("has_more", value(false), "bookmark", value(newBookmarkValue))); - return expectedPullStage; - }); - @SuppressWarnings("unchecked") - var runHandler = (MessageHandler) mock(MessageHandler.class); - var pullHandler = mock(PullMessageHandler.class); - - var runStage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - runHandler, - NoopLoggingProvider.INSTANCE, - valueFactory); - var pullStage = protocol.pull(connection, 0, UNLIMITED_FETCH_SIZE, pullHandler, valueFactory); - - assertEquals(expectedRunStage, runStage); - assertEquals(expectedPullStage, pullStage); - var runMessage = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(runMessage), any(RunResponseHandler.class)); - var pullMessage = new PullMessage(UNLIMITED_FETCH_SIZE, 0L, valueFactory); - then(connection).should().write(eq(pullMessage), any(PullResponseHandlerImpl.class)); - then(runHandler).should().onSummary(any()); - then(pullHandler) - .should() - .onSummary(new PullResponseHandlerImpl.PullSummaryImpl( - false, Map.of("has_more", value(false), "bookmark", value(newBookmarkValue)))); - } - - protected void testRunInUnmanagedTransactionAndWaitForRunResponse(boolean success) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - if (success) { - runHandler.onSuccess(emptyMap()); - } else { - runHandler.onFailure(error); - } - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - if (success) { - then(handler).should().onSummary(any()); - } else { - then(handler).should().onError(error); - } - } - - protected void testRunAndWaitForRunResponse( - boolean autoCommitTx, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var initialBookmarks = Collections.singleton("neo4j:bookmark:v1:tx987"); - - if (autoCommitTx) { - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - initialBookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - initialBookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private void testDatabaseNameSupport(boolean autoCommitTx) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - if (autoCommitTx) { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private static Value value(Object value) { - return valueFactory.value(value); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v53/BoltProtocolV53Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v53/BoltProtocolV53Test.java deleted file mode 100644 index d9d35eddb4..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v53/BoltProtocolV53Test.java +++ /dev/null @@ -1,790 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v53; - -import static java.time.Duration.ofSeconds; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import io.netty.channel.embedded.EmbeddedChannel; -import java.time.Clock; -import java.time.Duration; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.mockito.stubbing.Answer; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.BeginTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.CommitTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.PullResponseHandlerImpl; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RollbackTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RunResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.PullMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.LogonMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v51.MessageFormatV51; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public class BoltProtocolV53Test { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private static final String query = "RETURN $x"; - private static final Map query_params = singletonMap("x", value(42)); - private static final long UNLIMITED_FETCH_SIZE = -1; - private static final Duration txTimeout = ofSeconds(12); - private static final Map txMetadata = singletonMap("x", value(42)); - - protected final BoltProtocol protocol = createProtocol(); - private final EmbeddedChannel channel = new EmbeddedChannel(); - private final InboundMessageDispatcher messageDispatcher = - new InboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE); - - @SuppressWarnings("SameReturnValue") - protected BoltProtocol createProtocol() { - return BoltProtocolV53.INSTANCE; - } - - @BeforeEach - void beforeEach() { - ChannelAttributes.setMessageDispatcher(channel, messageDispatcher); - } - - @AfterEach - void afterEach() { - channel.finishAndReleaseAll(); - } - - @Test - void shouldCreateMessageFormat() { - assertInstanceOf(expectedMessageFormatType(), protocol.createMessageFormat()); - } - - @Test - void shouldInitializeChannel() { - var clock = mock(Clock.class); - var time = 1L; - when(clock.millis()).thenReturn(time); - - var latestAuthMillisFuture = new CompletableFuture(); - - var future = protocol.initializeChannel( - channel, - "MyDriver/0.0.1", - null, - Collections.emptyMap(), - RoutingContext.EMPTY, - null, - clock, - latestAuthMillisFuture, - valueFactory) - .toCompletableFuture(); - - assertEquals(2, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertInstanceOf(LogonMessage.class, channel.outboundMessages().poll()); - assertEquals(2, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - var metadata = Map.of( - "server", value("Neo4j/3.5.0"), - "connection_id", value("bolt-42")); - - messageDispatcher.handleSuccessMessage(metadata); - messageDispatcher.handleSuccessMessage(Collections.emptyMap()); - - assertTrue(future.isDone()); - assertEquals(channel, future.join()); - verify(clock).millis(); - assertTrue(latestAuthMillisFuture.isDone()); - assertEquals(time, latestAuthMillisFuture.join()); - } - - @Test - void shouldBeginTransactionWithoutBookmark() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarks() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx100"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarksAndConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx4242"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldCommitTransaction() { - var bookmarkString = "neo4j:bookmark:v1:tx4242"; - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var commitHandler = (CommitTxResponseHandler) invocation.getArgument(1); - commitHandler.onSuccess(Map.of("bookmark", value(bookmarkString))); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.commitTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(CommitMessage.COMMIT), any(CommitTxResponseHandler.class)); - then(handler).should().onSummary(bookmarkString); - } - - @Test - void shouldRollbackTransaction() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var rollbackHandler = (RollbackTxResponseHandler) invocation.getArgument(1); - rollbackHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.rollbackTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(RollbackMessage.ROLLBACK), any(RollbackTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx65"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse(Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx163"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInUnmanagedTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(false, null, Collections.emptyMap(), mode); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForSuccessRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(true); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForFailureRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(false); - } - - @Test - void databaseNameInBeginTransaction() { - testDatabaseNameSupport(false); - } - - @Test - void databaseNameForAutoCommitTransactions() { - testDatabaseNameSupport(true); - } - - @Test - void shouldSupportDatabaseNameInBeginTransaction() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.beginTransaction( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldNotSupportDatabaseNameForAutoCommitTransactions() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.runAuto( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldReturnFailedStageWithNoConnectionInteractionsOnTelemetry() { - var connection = mock(Connection.class); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var future = protocol.telemetry(connection, 1, handler).toCompletableFuture(); - - assertTrue(future.isCompletedExceptionally()); - then(connection).shouldHaveNoInteractions(); - } - - private Class expectedMessageFormatType() { - return MessageFormatV51.class; - } - - private void testFailedRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onFailure(error); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onError(error); - } - - private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedRunStage = CompletableFuture.completedStage(null); - var expectedPullStage = CompletableFuture.completedStage(null); - var newBookmarkValue = "neo4j:bookmark:v1:tx98765"; - given(connection.write(any(), any())) - .willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedRunStage; - }) - .willAnswer((Answer>) invocation -> { - var pullHandler = (PullResponseHandlerImpl) invocation.getArgument(1); - pullHandler.onSuccess(Map.of("has_more", value(false), "bookmark", value(newBookmarkValue))); - return expectedPullStage; - }); - @SuppressWarnings("unchecked") - var runHandler = (MessageHandler) mock(MessageHandler.class); - var pullHandler = mock(PullMessageHandler.class); - - var runStage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - runHandler, - NoopLoggingProvider.INSTANCE, - valueFactory); - var pullStage = protocol.pull(connection, 0, UNLIMITED_FETCH_SIZE, pullHandler, valueFactory); - - assertEquals(expectedRunStage, runStage); - assertEquals(expectedPullStage, pullStage); - var runMessage = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(runMessage), any(RunResponseHandler.class)); - var pullMessage = new PullMessage(UNLIMITED_FETCH_SIZE, 0L, valueFactory); - then(connection).should().write(eq(pullMessage), any(PullResponseHandlerImpl.class)); - then(runHandler).should().onSummary(any()); - then(pullHandler) - .should() - .onSummary(new PullResponseHandlerImpl.PullSummaryImpl( - false, Map.of("has_more", value(false), "bookmark", value(newBookmarkValue)))); - } - - protected void testRunInUnmanagedTransactionAndWaitForRunResponse(boolean success) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - if (success) { - runHandler.onSuccess(emptyMap()); - } else { - runHandler.onFailure(error); - } - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - if (success) { - then(handler).should().onSummary(any()); - } else { - then(handler).should().onError(error); - } - } - - protected void testRunAndWaitForRunResponse( - boolean autoCommitTx, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var initialBookmarks = Collections.singleton("neo4j:bookmark:v1:tx987"); - - if (autoCommitTx) { - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - initialBookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - initialBookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private void testDatabaseNameSupport(boolean autoCommitTx) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - if (autoCommitTx) { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private static Value value(Object value) { - return valueFactory.value(value); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v54/BoltProtocolV54Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v54/BoltProtocolV54Test.java deleted file mode 100644 index b354e0c497..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v54/BoltProtocolV54Test.java +++ /dev/null @@ -1,791 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v54; - -import static java.time.Duration.ofSeconds; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import io.netty.channel.embedded.EmbeddedChannel; -import java.time.Clock; -import java.time.Duration; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.mockito.stubbing.Answer; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.BeginTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.CommitTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.PullResponseHandlerImpl; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RollbackTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RunResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.PullMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.LogonMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.TelemetryMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public class BoltProtocolV54Test { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private static final String query = "RETURN $x"; - private static final Map query_params = singletonMap("x", value(42)); - private static final long UNLIMITED_FETCH_SIZE = -1; - private static final Duration txTimeout = ofSeconds(12); - private static final Map txMetadata = singletonMap("x", value(42)); - - protected final BoltProtocol protocol = createProtocol(); - private final EmbeddedChannel channel = new EmbeddedChannel(); - private final InboundMessageDispatcher messageDispatcher = - new InboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE); - - @SuppressWarnings("SameReturnValue") - protected BoltProtocol createProtocol() { - return BoltProtocolV54.INSTANCE; - } - - @BeforeEach - void beforeEach() { - ChannelAttributes.setMessageDispatcher(channel, messageDispatcher); - } - - @AfterEach - void afterEach() { - channel.finishAndReleaseAll(); - } - - @Test - void shouldCreateMessageFormat() { - assertInstanceOf(expectedMessageFormatType(), protocol.createMessageFormat()); - } - - @Test - void shouldInitializeChannel() { - var clock = mock(Clock.class); - var time = 1L; - when(clock.millis()).thenReturn(time); - - var latestAuthMillisFuture = new CompletableFuture(); - - var future = protocol.initializeChannel( - channel, - "MyDriver/0.0.1", - null, - Collections.emptyMap(), - RoutingContext.EMPTY, - null, - clock, - latestAuthMillisFuture, - valueFactory) - .toCompletableFuture(); - - assertEquals(2, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertInstanceOf(LogonMessage.class, channel.outboundMessages().poll()); - assertEquals(2, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - var metadata = Map.of( - "server", value("Neo4j/3.5.0"), - "connection_id", value("bolt-42")); - - messageDispatcher.handleSuccessMessage(metadata); - messageDispatcher.handleSuccessMessage(Collections.emptyMap()); - - assertTrue(future.isDone()); - assertEquals(channel, future.join()); - verify(clock).millis(); - assertTrue(latestAuthMillisFuture.isDone()); - assertEquals(time, latestAuthMillisFuture.join()); - } - - @Test - void shouldBeginTransactionWithoutBookmark() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarks() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx100"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarksAndConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx4242"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldCommitTransaction() { - var bookmarkString = "neo4j:bookmark:v1:tx4242"; - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var commitHandler = (CommitTxResponseHandler) invocation.getArgument(1); - commitHandler.onSuccess(Map.of("bookmark", value(bookmarkString))); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.commitTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(CommitMessage.COMMIT), any(CommitTxResponseHandler.class)); - then(handler).should().onSummary(bookmarkString); - } - - @Test - void shouldRollbackTransaction() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var rollbackHandler = (RollbackTxResponseHandler) invocation.getArgument(1); - rollbackHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.rollbackTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(RollbackMessage.ROLLBACK), any(RollbackTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx65"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse(Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx163"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInUnmanagedTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(false, null, Collections.emptyMap(), mode); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForSuccessRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(true); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForFailureRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(false); - } - - @Test - void databaseNameInBeginTransaction() { - testDatabaseNameSupport(false); - } - - @Test - void databaseNameForAutoCommitTransactions() { - testDatabaseNameSupport(true); - } - - @Test - void shouldSupportDatabaseNameInBeginTransaction() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.beginTransaction( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldNotSupportDatabaseNameForAutoCommitTransactions() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.runAuto( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldTelemetrySendTelemetryMessage() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - var expectedApi = 1; - given(connection.write(any(), any())).willReturn(expectedStage); - - var future = protocol.telemetry(connection, expectedApi, mock()); - - assertEquals(expectedStage, future); - then(connection).should().write(eq(new TelemetryMessage(expectedApi)), any()); - } - - private Class expectedMessageFormatType() { - return MessageFormatV54.class; - } - - private void testFailedRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onFailure(error); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onError(error); - } - - private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedRunStage = CompletableFuture.completedStage(null); - var expectedPullStage = CompletableFuture.completedStage(null); - var newBookmarkValue = "neo4j:bookmark:v1:tx98765"; - given(connection.write(any(), any())) - .willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedRunStage; - }) - .willAnswer((Answer>) invocation -> { - var pullHandler = (PullResponseHandlerImpl) invocation.getArgument(1); - pullHandler.onSuccess(Map.of("has_more", value(false), "bookmark", value(newBookmarkValue))); - return expectedPullStage; - }); - @SuppressWarnings("unchecked") - var runHandler = (MessageHandler) mock(MessageHandler.class); - var pullHandler = mock(PullMessageHandler.class); - - var runStage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - runHandler, - NoopLoggingProvider.INSTANCE, - valueFactory); - var pullStage = protocol.pull(connection, 0, UNLIMITED_FETCH_SIZE, pullHandler, valueFactory); - - assertEquals(expectedRunStage, runStage); - assertEquals(expectedPullStage, pullStage); - var runMessage = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(runMessage), any(RunResponseHandler.class)); - var pullMessage = new PullMessage(UNLIMITED_FETCH_SIZE, 0L, valueFactory); - then(connection).should().write(eq(pullMessage), any(PullResponseHandlerImpl.class)); - then(runHandler).should().onSummary(any()); - then(pullHandler) - .should() - .onSummary(new PullResponseHandlerImpl.PullSummaryImpl( - false, Map.of("has_more", value(false), "bookmark", value(newBookmarkValue)))); - } - - protected void testRunInUnmanagedTransactionAndWaitForRunResponse(boolean success) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - if (success) { - runHandler.onSuccess(emptyMap()); - } else { - runHandler.onFailure(error); - } - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - if (success) { - then(handler).should().onSummary(any()); - } else { - then(handler).should().onError(error); - } - } - - protected void testRunAndWaitForRunResponse( - boolean autoCommitTx, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var initialBookmarks = Collections.singleton("neo4j:bookmark:v1:tx987"); - - if (autoCommitTx) { - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - initialBookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - initialBookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private void testDatabaseNameSupport(boolean autoCommitTx) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - if (autoCommitTx) { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private static Value value(Object value) { - return valueFactory.value(value); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v54/MessageFormatV54Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v54/MessageFormatV54Test.java deleted file mode 100644 index 60217066a6..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v54/MessageFormatV54Test.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v54; - -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.mockito.Mockito.mock; - -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v5.MessageReaderV5; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -class MessageFormatV54Test { - private static final MessageFormat format = BoltProtocolV54.INSTANCE.createMessageFormat(); - - @Test - void shouldCreateCorrectWriter() { - var writer = format.newWriter(mock(PackOutput.class), mock(ValueFactory.class)); - - assertInstanceOf(MessageWriterV54.class, writer); - } - - @Test - void shouldCreateCorrectReader() { - var reader = format.newReader(mock(PackInput.class), mock(ValueFactory.class)); - - assertInstanceOf(MessageReaderV5.class, reader); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v54/MessageWriterV54Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v54/MessageWriterV54Test.java deleted file mode 100644 index 8598533476..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v54/MessageWriterV54Test.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v54; - -import static java.time.Duration.ofSeconds; -import static java.util.Calendar.DECEMBER; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.neo4j.driver.internal.bolt.api.AccessMode.READ; -import static org.neo4j.driver.internal.bolt.api.AccessMode.WRITE; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage.COMMIT; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage.DISCARD_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage.GOODBYE; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullAllMessage.PULL_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage.RESET; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage.ROLLBACK; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.BoltAgentUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RouteMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.TelemetryMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.AbstractMessageWriterTestBase; - -public class MessageWriterV54Test extends AbstractMessageWriterTestBase { - @Override - protected MessageFormat.Writer newWriter(PackOutput output) { - return BoltProtocolV54.INSTANCE.createMessageFormat().newWriter(output, valueFactory); - } - - @Override - protected Stream supportedMessages() { - return Stream.of( - // Bolt V2 Data Types - unmanagedTxRunMessage("RETURN $point", singletonMap("point", valueFactory.point(42, 12.99, -180.0))), - unmanagedTxRunMessage( - "RETURN $point", singletonMap("point", valueFactory.point(42, 0.51, 2.99, 100.123))), - unmanagedTxRunMessage( - "RETURN $date", singletonMap("date", valueFactory.value(LocalDate.ofEpochDay(2147483650L)))), - unmanagedTxRunMessage( - "RETURN $time", - singletonMap("time", valueFactory.value(OffsetTime.of(4, 16, 20, 999, ZoneOffset.MIN)))), - unmanagedTxRunMessage( - "RETURN $time", singletonMap("time", valueFactory.value(LocalTime.of(12, 9, 18, 999_888)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", valueFactory.value(LocalDateTime.of(2049, DECEMBER, 12, 17, 25, 49, 199)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value(ZonedDateTime.of( - 2000, 1, 10, 12, 2, 49, 300, ZoneOffset.ofHoursMinutes(9, 30))))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value( - ZonedDateTime.of(2000, 1, 10, 12, 2, 49, 300, ZoneId.of("Europe/Stockholm"))))), - - // New Bolt V4 messages - new PullMessage(100, 200, valueFactory), - new DiscardMessage(300, 400, valueFactory), - - // Bolt V3 messages - new HelloMessage( - "MyDriver/1.2.3", - BoltAgentUtil.VALUE, - Map.of( - "scheme", - valueFactory.value("basic"), - "principal", - valueFactory.value("neo4j"), - "credentials", - valueFactory.value("neo4j")), - Collections.emptyMap(), - false, - null, - false, - valueFactory), - GOODBYE, - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - READ, - defaultDatabase(), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - WRITE, - database("foo"), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - COMMIT, - ROLLBACK, - RESET, - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - defaultDatabase(), - READ, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - database("foo"), - WRITE, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN 1", Collections.emptyMap()), - - // Bolt V3 messages with struct values - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - defaultDatabase(), - READ, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - database("foo"), - WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN $x", singletonMap("x", valueFactory.point(42, 1, 2, 3))), - - // New 4.3 Messages - routeMessage(), - // New 5.4 message - telemetryMessage()); - } - - @Override - protected Stream unsupportedMessages() { - return Stream.of( - // Bolt V1, V2 and V3 messages - PULL_ALL, DISCARD_ALL); - } - - private RouteMessage routeMessage() { - Map routeContext = new HashMap<>(); - routeContext.put("someContext", valueFactory.value(124)); - return new RouteMessage(routeContext, Collections.emptySet(), "dbName", null); - } - - private TelemetryMessage telemetryMessage() { - return new TelemetryMessage(1); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v55/BoltProtocolV55Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v55/BoltProtocolV55Test.java deleted file mode 100644 index f17664848c..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v55/BoltProtocolV55Test.java +++ /dev/null @@ -1,792 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v55; - -import static java.time.Duration.ofSeconds; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import io.netty.channel.embedded.EmbeddedChannel; -import java.time.Clock; -import java.time.Duration; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.mockito.stubbing.Answer; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.BeginTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.CommitTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.PullResponseHandlerImpl; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RollbackTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RunResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.PullMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.LogonMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.TelemetryMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v54.MessageFormatV54; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public class BoltProtocolV55Test { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private static final String query = "RETURN $x"; - private static final Map query_params = singletonMap("x", value(42)); - private static final long UNLIMITED_FETCH_SIZE = -1; - private static final Duration txTimeout = ofSeconds(12); - private static final Map txMetadata = singletonMap("x", value(42)); - - protected final BoltProtocol protocol = createProtocol(); - private final EmbeddedChannel channel = new EmbeddedChannel(); - private final InboundMessageDispatcher messageDispatcher = - new InboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE); - - @SuppressWarnings("SameReturnValue") - protected BoltProtocol createProtocol() { - return BoltProtocolV55.INSTANCE; - } - - @BeforeEach - void beforeEach() { - ChannelAttributes.setMessageDispatcher(channel, messageDispatcher); - } - - @AfterEach - void afterEach() { - channel.finishAndReleaseAll(); - } - - @Test - void shouldCreateMessageFormat() { - assertInstanceOf(expectedMessageFormatType(), protocol.createMessageFormat()); - } - - @Test - void shouldInitializeChannel() { - var clock = mock(Clock.class); - var time = 1L; - when(clock.millis()).thenReturn(time); - - var latestAuthMillisFuture = new CompletableFuture(); - - var future = protocol.initializeChannel( - channel, - "MyDriver/0.0.1", - null, - Collections.emptyMap(), - RoutingContext.EMPTY, - null, - clock, - latestAuthMillisFuture, - valueFactory) - .toCompletableFuture(); - - assertEquals(2, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertInstanceOf(LogonMessage.class, channel.outboundMessages().poll()); - assertEquals(2, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - var metadata = Map.of( - "server", value("Neo4j/3.5.0"), - "connection_id", value("bolt-42")); - - messageDispatcher.handleSuccessMessage(metadata); - messageDispatcher.handleSuccessMessage(Collections.emptyMap()); - - assertTrue(future.isDone()); - assertEquals(channel, future.join()); - verify(clock).millis(); - assertTrue(latestAuthMillisFuture.isDone()); - assertEquals(time, latestAuthMillisFuture.join()); - } - - @Test - void shouldBeginTransactionWithoutBookmark() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarks() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx100"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarksAndConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx4242"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldCommitTransaction() { - var bookmarkString = "neo4j:bookmark:v1:tx4242"; - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var commitHandler = (CommitTxResponseHandler) invocation.getArgument(1); - commitHandler.onSuccess(Map.of("bookmark", value(bookmarkString))); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.commitTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(CommitMessage.COMMIT), any(CommitTxResponseHandler.class)); - then(handler).should().onSummary(bookmarkString); - } - - @Test - void shouldRollbackTransaction() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var rollbackHandler = (RollbackTxResponseHandler) invocation.getArgument(1); - rollbackHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.rollbackTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(RollbackMessage.ROLLBACK), any(RollbackTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx65"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse(Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx163"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInUnmanagedTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(false, null, Collections.emptyMap(), mode); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForSuccessRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(true); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForFailureRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(false); - } - - @Test - void databaseNameInBeginTransaction() { - testDatabaseNameSupport(false); - } - - @Test - void databaseNameForAutoCommitTransactions() { - testDatabaseNameSupport(true); - } - - @Test - void shouldSupportDatabaseNameInBeginTransaction() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.beginTransaction( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldNotSupportDatabaseNameForAutoCommitTransactions() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.runAuto( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldTelemetrySendTelemetryMessage() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - var expectedApi = 1; - given(connection.write(any(), any())).willReturn(expectedStage); - - var future = protocol.telemetry(connection, expectedApi, mock()); - - assertEquals(expectedStage, future); - then(connection).should().write(eq(new TelemetryMessage(expectedApi)), any()); - } - - private Class expectedMessageFormatType() { - return MessageFormatV54.class; - } - - private void testFailedRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onFailure(error); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onError(error); - } - - private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedRunStage = CompletableFuture.completedStage(null); - var expectedPullStage = CompletableFuture.completedStage(null); - var newBookmarkValue = "neo4j:bookmark:v1:tx98765"; - given(connection.write(any(), any())) - .willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedRunStage; - }) - .willAnswer((Answer>) invocation -> { - var pullHandler = (PullResponseHandlerImpl) invocation.getArgument(1); - pullHandler.onSuccess(Map.of("has_more", value(false), "bookmark", value(newBookmarkValue))); - return expectedPullStage; - }); - @SuppressWarnings("unchecked") - var runHandler = (MessageHandler) mock(MessageHandler.class); - var pullHandler = mock(PullMessageHandler.class); - - var runStage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - runHandler, - NoopLoggingProvider.INSTANCE, - valueFactory); - var pullStage = protocol.pull(connection, 0, UNLIMITED_FETCH_SIZE, pullHandler, valueFactory); - - assertEquals(expectedRunStage, runStage); - assertEquals(expectedPullStage, pullStage); - var runMessage = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(runMessage), any(RunResponseHandler.class)); - var pullMessage = new PullMessage(UNLIMITED_FETCH_SIZE, 0L, valueFactory); - then(connection).should().write(eq(pullMessage), any(PullResponseHandlerImpl.class)); - then(runHandler).should().onSummary(any()); - then(pullHandler) - .should() - .onSummary(new PullResponseHandlerImpl.PullSummaryImpl( - false, Map.of("has_more", value(false), "bookmark", value(newBookmarkValue)))); - } - - protected void testRunInUnmanagedTransactionAndWaitForRunResponse(boolean success) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - if (success) { - runHandler.onSuccess(emptyMap()); - } else { - runHandler.onFailure(error); - } - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - if (success) { - then(handler).should().onSummary(any()); - } else { - then(handler).should().onError(error); - } - } - - protected void testRunAndWaitForRunResponse( - boolean autoCommitTx, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var initialBookmarks = Collections.singleton("neo4j:bookmark:v1:tx987"); - - if (autoCommitTx) { - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - initialBookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - initialBookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private void testDatabaseNameSupport(boolean autoCommitTx) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - if (autoCommitTx) { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private static Value value(Object value) { - return valueFactory.value(value); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v56/BoltProtocolV56Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v56/BoltProtocolV56Test.java deleted file mode 100644 index 58c7e16a30..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v56/BoltProtocolV56Test.java +++ /dev/null @@ -1,792 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v56; - -import static java.time.Duration.ofSeconds; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import io.netty.channel.embedded.EmbeddedChannel; -import java.time.Clock; -import java.time.Duration; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.mockito.stubbing.Answer; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.BeginTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.CommitTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.PullResponseHandlerImpl; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RollbackTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RunResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.PullMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.LogonMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.TelemetryMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v54.MessageFormatV54; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public class BoltProtocolV56Test { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private static final String query = "RETURN $x"; - private static final Map query_params = singletonMap("x", value(42)); - private static final long UNLIMITED_FETCH_SIZE = -1; - private static final Duration txTimeout = ofSeconds(12); - private static final Map txMetadata = singletonMap("x", value(42)); - - protected final BoltProtocol protocol = createProtocol(); - private final EmbeddedChannel channel = new EmbeddedChannel(); - private final InboundMessageDispatcher messageDispatcher = - new InboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE); - - @SuppressWarnings("SameReturnValue") - protected BoltProtocol createProtocol() { - return BoltProtocolV56.INSTANCE; - } - - @BeforeEach - void beforeEach() { - ChannelAttributes.setMessageDispatcher(channel, messageDispatcher); - } - - @AfterEach - void afterEach() { - channel.finishAndReleaseAll(); - } - - @Test - void shouldCreateMessageFormat() { - assertInstanceOf(expectedMessageFormatType(), protocol.createMessageFormat()); - } - - @Test - void shouldInitializeChannel() { - var clock = mock(Clock.class); - var time = 1L; - when(clock.millis()).thenReturn(time); - - var latestAuthMillisFuture = new CompletableFuture(); - - var future = protocol.initializeChannel( - channel, - "MyDriver/0.0.1", - null, - Collections.emptyMap(), - RoutingContext.EMPTY, - null, - clock, - latestAuthMillisFuture, - valueFactory) - .toCompletableFuture(); - - assertEquals(2, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertInstanceOf(LogonMessage.class, channel.outboundMessages().poll()); - assertEquals(2, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - var metadata = Map.of( - "server", value("Neo4j/3.5.0"), - "connection_id", value("bolt-42")); - - messageDispatcher.handleSuccessMessage(metadata); - messageDispatcher.handleSuccessMessage(Collections.emptyMap()); - - assertTrue(future.isDone()); - assertEquals(channel, future.join()); - verify(clock).millis(); - assertTrue(latestAuthMillisFuture.isDone()); - assertEquals(time, latestAuthMillisFuture.join()); - } - - @Test - void shouldBeginTransactionWithoutBookmark() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarks() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx100"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarksAndConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx4242"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - bookmarks, - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldCommitTransaction() { - var bookmarkString = "neo4j:bookmark:v1:tx4242"; - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var commitHandler = (CommitTxResponseHandler) invocation.getArgument(1); - commitHandler.onSuccess(Map.of("bookmark", value(bookmarkString))); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.commitTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(CommitMessage.COMMIT), any(CommitTxResponseHandler.class)); - then(handler).should().onSummary(bookmarkString); - } - - @Test - void shouldRollbackTransaction() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var rollbackHandler = (RollbackTxResponseHandler) invocation.getArgument(1); - rollbackHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.rollbackTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(RollbackMessage.ROLLBACK), any(RollbackTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx65"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse(Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx163"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInUnmanagedTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(false, null, Collections.emptyMap(), mode); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForSuccessRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(true); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForFailureRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(false); - } - - @Test - void databaseNameInBeginTransaction() { - testDatabaseNameSupport(false); - } - - @Test - void databaseNameForAutoCommitTransactions() { - testDatabaseNameSupport(true); - } - - @Test - void shouldSupportDatabaseNameInBeginTransaction() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.beginTransaction( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldNotSupportDatabaseNameForAutoCommitTransactions() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.runAuto( - connection, - database("foo"), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldTelemetrySendTelemetryMessage() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - var expectedApi = 1; - given(connection.write(any(), any())).willReturn(expectedStage); - - var future = protocol.telemetry(connection, expectedApi, mock()); - - assertEquals(expectedStage, future); - then(connection).should().write(eq(new TelemetryMessage(expectedApi)), any()); - } - - private Class expectedMessageFormatType() { - return MessageFormatV54.class; - } - - private void testFailedRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onFailure(error); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onError(error); - } - - private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedRunStage = CompletableFuture.completedStage(null); - var expectedPullStage = CompletableFuture.completedStage(null); - var newBookmarkValue = "neo4j:bookmark:v1:tx98765"; - given(connection.write(any(), any())) - .willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedRunStage; - }) - .willAnswer((Answer>) invocation -> { - var pullHandler = (PullResponseHandlerImpl) invocation.getArgument(1); - pullHandler.onSuccess(Map.of("has_more", value(false), "bookmark", value(newBookmarkValue))); - return expectedPullStage; - }); - @SuppressWarnings("unchecked") - var runHandler = (MessageHandler) mock(MessageHandler.class); - var pullHandler = mock(PullMessageHandler.class); - - var runStage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - runHandler, - NoopLoggingProvider.INSTANCE, - valueFactory); - var pullStage = protocol.pull(connection, 0, UNLIMITED_FETCH_SIZE, pullHandler, valueFactory); - - assertEquals(expectedRunStage, runStage); - assertEquals(expectedPullStage, pullStage); - var runMessage = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(runMessage), any(RunResponseHandler.class)); - var pullMessage = new PullMessage(UNLIMITED_FETCH_SIZE, 0L, valueFactory); - then(connection).should().write(eq(pullMessage), any(PullResponseHandlerImpl.class)); - then(runHandler).should().onSummary(any()); - then(pullHandler) - .should() - .onSummary(new PullResponseHandlerImpl.PullSummaryImpl( - false, Map.of("has_more", value(false), "bookmark", value(newBookmarkValue)))); - } - - protected void testRunInUnmanagedTransactionAndWaitForRunResponse(boolean success) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - if (success) { - runHandler.onSuccess(emptyMap()); - } else { - runHandler.onFailure(error); - } - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - if (success) { - then(handler).should().onSummary(any()); - } else { - then(handler).should().onError(error); - } - } - - protected void testRunAndWaitForRunResponse( - boolean autoCommitTx, - Duration txTimeout, - Map txMetadata, - org.neo4j.driver.internal.bolt.api.AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var initialBookmarks = Collections.singleton("neo4j:bookmark:v1:tx987"); - - if (autoCommitTx) { - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - initialBookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - initialBookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private void testDatabaseNameSupport(boolean autoCommitTx) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - if (autoCommitTx) { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - org.neo4j.driver.internal.bolt.api.AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private static Value value(Object value) { - return valueFactory.value(value); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v56/MessageFormatV56Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v56/MessageFormatV56Test.java deleted file mode 100644 index 0d8a0f6e10..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v56/MessageFormatV56Test.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v56; - -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.mockito.Mockito.mock; - -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v5.MessageReaderV5; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v54.MessageWriterV54; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -class MessageFormatV56Test { - private static final MessageFormat format = BoltProtocolV56.INSTANCE.createMessageFormat(); - - @Test - void shouldCreateCorrectWriter() { - var writer = format.newWriter(mock(PackOutput.class), mock(ValueFactory.class)); - - assertInstanceOf(MessageWriterV54.class, writer); - } - - @Test - void shouldCreateCorrectReader() { - var reader = format.newReader(mock(PackInput.class), mock(ValueFactory.class)); - - assertInstanceOf(MessageReaderV5.class, reader); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v56/MessageWriterV56Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v56/MessageWriterV56Test.java deleted file mode 100644 index d6e12fcadc..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v56/MessageWriterV56Test.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v56; - -import static java.time.Duration.ofSeconds; -import static java.util.Calendar.DECEMBER; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.neo4j.driver.internal.bolt.api.AccessMode.READ; -import static org.neo4j.driver.internal.bolt.api.AccessMode.WRITE; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage.COMMIT; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage.DISCARD_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage.GOODBYE; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullAllMessage.PULL_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage.RESET; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage.ROLLBACK; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.BoltAgentUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RouteMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.TelemetryMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.AbstractMessageWriterTestBase; - -public class MessageWriterV56Test extends AbstractMessageWriterTestBase { - @Override - protected MessageFormat.Writer newWriter(PackOutput output) { - return BoltProtocolV56.INSTANCE.createMessageFormat().newWriter(output, valueFactory); - } - - @Override - protected Stream supportedMessages() { - return Stream.of( - // Bolt V2 Data Types - unmanagedTxRunMessage("RETURN $point", singletonMap("point", valueFactory.point(42, 12.99, -180.0))), - unmanagedTxRunMessage( - "RETURN $point", singletonMap("point", valueFactory.point(42, 0.51, 2.99, 100.123))), - unmanagedTxRunMessage( - "RETURN $date", singletonMap("date", valueFactory.value(LocalDate.ofEpochDay(2147483650L)))), - unmanagedTxRunMessage( - "RETURN $time", - singletonMap("time", valueFactory.value(OffsetTime.of(4, 16, 20, 999, ZoneOffset.MIN)))), - unmanagedTxRunMessage( - "RETURN $time", singletonMap("time", valueFactory.value(LocalTime.of(12, 9, 18, 999_888)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", valueFactory.value(LocalDateTime.of(2049, DECEMBER, 12, 17, 25, 49, 199)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value(ZonedDateTime.of( - 2000, 1, 10, 12, 2, 49, 300, ZoneOffset.ofHoursMinutes(9, 30))))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value( - ZonedDateTime.of(2000, 1, 10, 12, 2, 49, 300, ZoneId.of("Europe/Stockholm"))))), - - // New Bolt V4 messages - new PullMessage(100, 200, valueFactory), - new DiscardMessage(300, 400, valueFactory), - - // Bolt V3 messages - new HelloMessage( - "MyDriver/1.2.3", - BoltAgentUtil.VALUE, - Map.of( - "scheme", - valueFactory.value("basic"), - "principal", - valueFactory.value("neo4j"), - "credentials", - valueFactory.value("neo4j")), - Collections.emptyMap(), - false, - null, - false, - valueFactory), - GOODBYE, - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - READ, - defaultDatabase(), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - WRITE, - database("foo"), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - COMMIT, - ROLLBACK, - RESET, - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - defaultDatabase(), - READ, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - database("foo"), - WRITE, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN 1", Collections.emptyMap()), - - // Bolt V3 messages with struct values - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - defaultDatabase(), - READ, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - database("foo"), - WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN $x", singletonMap("x", valueFactory.point(42, 1, 2, 3))), - - // New 4.3 Messages - routeMessage(), - // New 5.4 message - telemetryMessage()); - } - - @Override - protected Stream unsupportedMessages() { - return Stream.of( - // Bolt V1, V2 and V3 messages - PULL_ALL, DISCARD_ALL); - } - - private RouteMessage routeMessage() { - Map routeContext = new HashMap<>(); - routeContext.put("someContext", valueFactory.value(124)); - return new RouteMessage(routeContext, Collections.emptySet(), "dbName", null); - } - - private TelemetryMessage telemetryMessage() { - return new TelemetryMessage(1); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v57/BoltProtocolV57Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v57/BoltProtocolV57Test.java deleted file mode 100644 index 43fb831225..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v57/BoltProtocolV57Test.java +++ /dev/null @@ -1,782 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v57; - -import static java.time.Duration.ofSeconds; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import io.netty.channel.embedded.EmbeddedChannel; -import java.time.Clock; -import java.time.Duration; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.mockito.stubbing.Answer; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.BeginTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.CommitTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.PullResponseHandlerImpl; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RollbackTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RunResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.PullMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.LogonMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.TelemetryMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public class BoltProtocolV57Test { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private static final String query = "RETURN $x"; - private static final Map query_params = singletonMap("x", value(42)); - private static final long UNLIMITED_FETCH_SIZE = -1; - private static final Duration txTimeout = ofSeconds(12); - private static final Map txMetadata = singletonMap("x", value(42)); - - protected final BoltProtocol protocol = createProtocol(); - private final EmbeddedChannel channel = new EmbeddedChannel(); - private final InboundMessageDispatcher messageDispatcher = - new InboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE); - - @SuppressWarnings("SameReturnValue") - protected BoltProtocol createProtocol() { - return BoltProtocolV57.INSTANCE; - } - - @BeforeEach - void beforeEach() { - ChannelAttributes.setMessageDispatcher(channel, messageDispatcher); - } - - @AfterEach - void afterEach() { - channel.finishAndReleaseAll(); - } - - @Test - void shouldCreateMessageFormat() { - assertInstanceOf(expectedMessageFormatType(), protocol.createMessageFormat()); - } - - @Test - void shouldInitializeChannel() { - var clock = mock(Clock.class); - var time = 1L; - when(clock.millis()).thenReturn(time); - - var latestAuthMillisFuture = new CompletableFuture(); - - var future = protocol.initializeChannel( - channel, - "MyDriver/0.0.1", - null, - Collections.emptyMap(), - RoutingContext.EMPTY, - null, - clock, - latestAuthMillisFuture, - valueFactory) - .toCompletableFuture(); - - assertEquals(2, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertInstanceOf(LogonMessage.class, channel.outboundMessages().poll()); - assertEquals(2, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - var metadata = Map.of( - "server", value("Neo4j/3.5.0"), - "connection_id", value("bolt-42")); - - messageDispatcher.handleSuccessMessage(metadata); - messageDispatcher.handleSuccessMessage(Collections.emptyMap()); - - assertTrue(future.isDone()); - assertEquals(channel, future.join()); - verify(clock).millis(); - assertTrue(latestAuthMillisFuture.isDone()); - assertEquals(time, latestAuthMillisFuture.join()); - } - - @Test - void shouldBeginTransactionWithoutBookmark() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarks() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx100"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - AccessMode.WRITE, - null, - bookmarks, - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - null, - Collections.emptyMap(), - defaultDatabase(), - AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - AccessMode.WRITE, - null, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - txTimeout, - txMetadata, - defaultDatabase(), - AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarksAndConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx4242"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - AccessMode.WRITE, - null, - bookmarks, - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - txTimeout, - txMetadata, - defaultDatabase(), - AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldCommitTransaction() { - var bookmarkString = "neo4j:bookmark:v1:tx4242"; - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var commitHandler = (CommitTxResponseHandler) invocation.getArgument(1); - commitHandler.onSuccess(Map.of("bookmark", value(bookmarkString))); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.commitTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(CommitMessage.COMMIT), any(CommitTxResponseHandler.class)); - then(handler).should().onSummary(bookmarkString); - } - - @Test - void shouldRollbackTransaction() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var rollbackHandler = (RollbackTxResponseHandler) invocation.getArgument(1); - rollbackHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.rollbackTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(RollbackMessage.ROLLBACK), any(RollbackTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx65"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse(Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx163"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInUnmanagedTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(false, null, Collections.emptyMap(), mode); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForSuccessRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(true); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForFailureRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(false); - } - - @Test - void databaseNameInBeginTransaction() { - testDatabaseNameSupport(false); - } - - @Test - void databaseNameForAutoCommitTransactions() { - testDatabaseNameSupport(true); - } - - @Test - void shouldSupportDatabaseNameInBeginTransaction() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.beginTransaction( - connection, - database("foo"), - AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldNotSupportDatabaseNameForAutoCommitTransactions() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.runAuto( - connection, - database("foo"), - AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldTelemetrySendTelemetryMessage() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - var expectedApi = 1; - given(connection.write(any(), any())).willReturn(expectedStage); - - var future = protocol.telemetry(connection, expectedApi, mock()); - - assertEquals(expectedStage, future); - then(connection).should().write(eq(new TelemetryMessage(expectedApi)), any()); - } - - private Class expectedMessageFormatType() { - return MessageFormatV57.class; - } - - private void testFailedRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, Duration txTimeout, Map txMetadata, AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onFailure(error); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onError(error); - } - - private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, Duration txTimeout, Map txMetadata, AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedRunStage = CompletableFuture.completedStage(null); - var expectedPullStage = CompletableFuture.completedStage(null); - var newBookmarkValue = "neo4j:bookmark:v1:tx98765"; - given(connection.write(any(), any())) - .willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedRunStage; - }) - .willAnswer((Answer>) invocation -> { - var pullHandler = (PullResponseHandlerImpl) invocation.getArgument(1); - pullHandler.onSuccess(Map.of("has_more", value(false), "bookmark", value(newBookmarkValue))); - return expectedPullStage; - }); - @SuppressWarnings("unchecked") - var runHandler = (MessageHandler) mock(MessageHandler.class); - var pullHandler = mock(PullMessageHandler.class); - - var runStage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - runHandler, - NoopLoggingProvider.INSTANCE, - valueFactory); - var pullStage = protocol.pull(connection, 0, UNLIMITED_FETCH_SIZE, pullHandler, valueFactory); - - assertEquals(expectedRunStage, runStage); - assertEquals(expectedPullStage, pullStage); - var runMessage = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(runMessage), any(RunResponseHandler.class)); - var pullMessage = new PullMessage(UNLIMITED_FETCH_SIZE, 0L, valueFactory); - then(connection).should().write(eq(pullMessage), any(PullResponseHandlerImpl.class)); - then(runHandler).should().onSummary(any()); - then(pullHandler) - .should() - .onSummary(new PullResponseHandlerImpl.PullSummaryImpl( - false, Map.of("has_more", value(false), "bookmark", value(newBookmarkValue)))); - } - - protected void testRunInUnmanagedTransactionAndWaitForRunResponse(boolean success) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - if (success) { - runHandler.onSuccess(emptyMap()); - } else { - runHandler.onFailure(error); - } - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - if (success) { - then(handler).should().onSummary(any()); - } else { - then(handler).should().onError(error); - } - } - - protected void testRunAndWaitForRunResponse( - boolean autoCommitTx, Duration txTimeout, Map txMetadata, AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var initialBookmarks = Collections.singleton("neo4j:bookmark:v1:tx987"); - - if (autoCommitTx) { - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - initialBookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - initialBookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private void testDatabaseNameSupport(boolean autoCommitTx) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - if (autoCommitTx) { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - AccessMode.WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private static Value value(Object value) { - return valueFactory.value(value); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v57/MessageFormatV57Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v57/MessageFormatV57Test.java deleted file mode 100644 index 5360bbad3c..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v57/MessageFormatV57Test.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v57; - -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.mockito.Mockito.mock; - -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v54.MessageWriterV54; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -class MessageFormatV57Test { - private static final MessageFormat format = BoltProtocolV57.INSTANCE.createMessageFormat(); - - @Test - void shouldCreateCorrectWriter() { - var writer = format.newWriter(mock(PackOutput.class), mock(ValueFactory.class)); - - assertInstanceOf(MessageWriterV54.class, writer); - } - - @Test - void shouldCreateCorrectReader() { - var reader = format.newReader(mock(PackInput.class), mock(ValueFactory.class)); - - assertInstanceOf(MessageReaderV57.class, reader); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v57/MessageReaderV57Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v57/MessageReaderV57Test.java deleted file mode 100644 index 162c8b71a5..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v57/MessageReaderV57Test.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v57; - -import static java.util.Arrays.asList; -import static java.util.Calendar.APRIL; -import static java.util.Calendar.AUGUST; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.mockito.Mockito.mock; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneOffset; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Stream; -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.IgnoredMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.RecordMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.SuccessMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.AbstractMessageReaderTestBase; - -class MessageReaderV57Test extends AbstractMessageReaderTestBase { - private final Map DIAGNOSTIC_RECORD = Map.ofEntries( - Map.entry("OPERATION", valueFactory.value("")), - Map.entry("OPERATION_CODE", valueFactory.value("0")), - Map.entry("CURRENT_SCHEMA", valueFactory.value("/"))); - - @Override - protected Stream supportedMessages() { - return Stream.of( - // V2 Record types - record(valueFactory.point(42, 120.65, -99.2)), - record(valueFactory.point(42, 85.391, 98.8, 11.1)), - record(valueFactory.value(LocalDate.of(2012, AUGUST, 3))), - record(valueFactory.value(OffsetTime.of(23, 59, 59, 999, ZoneOffset.MAX))), - record(valueFactory.value(LocalTime.of(12, 25))), - record(valueFactory.value(LocalDateTime.of(1999, APRIL, 3, 19, 5, 5, 100_200_300))), - record(valueFactory.isoDuration( - Long.MAX_VALUE - 1, Integer.MAX_VALUE - 1, Short.MAX_VALUE - 1, Byte.MAX_VALUE - 1)), - record(valueFactory.isoDuration(17, 22, 99, 15)), - - // Bolt previous versions valid messages - IgnoredMessage.IGNORED, - new SuccessMessage(new HashMap<>()), - record(valueFactory.value(1337L)), - record(valueFactory.value(List.of("cat", valueFactory.value(null), "dog", valueFactory.value(null)))), - record(valueFactory.value(List.of("k", valueFactory.value(12), "a", valueFactory.value("banana")))), - record(valueFactory.value(asList( - valueFactory.value("k"), - valueFactory.value(12), - valueFactory.value("a"), - valueFactory.value("banana"))))); - } - - @Override - protected Stream unsupportedMessages() { - return Stream.of(DiscardAllMessage.DISCARD_ALL); - } - - @Override - protected MessageFormat.Reader newReader(PackInput input) { - return BoltProtocolV57.INSTANCE.createMessageFormat().newReader(input, valueFactory); - } - - @Test - void shouldInitGqlError() { - var messageReader = new MessageReaderV57(mock(), valueFactory); - var gqlStatus = valueFactory.value("gql_status"); - var description = valueFactory.value("description"); - var message = valueFactory.value("message"); - var params = Map.of( - "gql_status", gqlStatus, - "description", description, - "message", message); - - var gqlError = messageReader.unpackGqlError(params); - - assertEquals(gqlStatus.asString(), gqlError.gqlStatus()); - assertEquals(description.asString(), gqlError.statusDescription()); - assertEquals("N/A", gqlError.code()); - assertEquals(message.asString(), gqlError.message()); - assertEquals(DIAGNOSTIC_RECORD, gqlError.diagnosticRecord()); - assertNull(gqlError.cause()); - } - - @Test - void shouldInitGqlErrorWithMap() { - var messageReader = new MessageReaderV57(mock(), valueFactory); - var gqlStatus = valueFactory.value("gql_status"); - var description = valueFactory.value("description"); - var message = valueFactory.value("message"); - var map = Map.of("key", valueFactory.value("value")); - var params = Map.of( - "gql_status", gqlStatus, - "description", description, - "message", message, - "diagnostic_record", valueFactory.value(map)); - - var gqlError = messageReader.unpackGqlError(params); - - assertEquals(gqlStatus.asString(), gqlError.gqlStatus()); - assertEquals(description.asString(), gqlError.statusDescription()); - assertEquals("N/A", gqlError.code()); - assertEquals(message.asString(), gqlError.message()); - var test = new HashMap<>(DIAGNOSTIC_RECORD); - test.putAll(map); - assertEquals(test, gqlError.diagnosticRecord()); - assertNull(gqlError.cause()); - } - - private Message record(Value value) { - return new RecordMessage(new Value[] {value}); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v57/MessageWriterV57Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v57/MessageWriterV57Test.java deleted file mode 100644 index 6804182e29..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v57/MessageWriterV57Test.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v57; - -import static java.time.Duration.ofSeconds; -import static java.util.Calendar.DECEMBER; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.neo4j.driver.internal.bolt.api.AccessMode.READ; -import static org.neo4j.driver.internal.bolt.api.AccessMode.WRITE; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage.COMMIT; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage.DISCARD_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.GoodbyeMessage.GOODBYE; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullAllMessage.PULL_ALL; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage.RESET; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage.ROLLBACK; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.BoltAgentUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RouteMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.TelemetryMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging.AbstractMessageWriterTestBase; - -public class MessageWriterV57Test extends AbstractMessageWriterTestBase { - @Override - protected MessageFormat.Writer newWriter(PackOutput output) { - return BoltProtocolV57.INSTANCE.createMessageFormat().newWriter(output, valueFactory); - } - - @Override - protected Stream supportedMessages() { - return Stream.of( - // Bolt V2 Data Types - unmanagedTxRunMessage("RETURN $point", singletonMap("point", valueFactory.point(42, 12.99, -180.0))), - unmanagedTxRunMessage( - "RETURN $point", singletonMap("point", valueFactory.point(42, 0.51, 2.99, 100.123))), - unmanagedTxRunMessage( - "RETURN $date", singletonMap("date", valueFactory.value(LocalDate.ofEpochDay(2147483650L)))), - unmanagedTxRunMessage( - "RETURN $time", - singletonMap("time", valueFactory.value(OffsetTime.of(4, 16, 20, 999, ZoneOffset.MIN)))), - unmanagedTxRunMessage( - "RETURN $time", singletonMap("time", valueFactory.value(LocalTime.of(12, 9, 18, 999_888)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", valueFactory.value(LocalDateTime.of(2049, DECEMBER, 12, 17, 25, 49, 199)))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value(ZonedDateTime.of( - 2000, 1, 10, 12, 2, 49, 300, ZoneOffset.ofHoursMinutes(9, 30))))), - unmanagedTxRunMessage( - "RETURN $dateTime", - singletonMap( - "dateTime", - valueFactory.value( - ZonedDateTime.of(2000, 1, 10, 12, 2, 49, 300, ZoneId.of("Europe/Stockholm"))))), - - // New Bolt V4 messages - new PullMessage(100, 200, valueFactory), - new DiscardMessage(300, 400, valueFactory), - - // Bolt V3 messages - new HelloMessage( - "MyDriver/1.2.3", - BoltAgentUtil.VALUE, - Map.of( - "scheme", - valueFactory.value("basic"), - "principal", - valueFactory.value("neo4j"), - "credentials", - valueFactory.value("neo4j")), - Collections.emptyMap(), - false, - null, - false, - valueFactory), - GOODBYE, - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - READ, - defaultDatabase(), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - new BeginMessage( - Collections.singleton("neo4j:bookmark:v1:tx123"), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - WRITE, - database("foo"), - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - COMMIT, - ROLLBACK, - RESET, - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - defaultDatabase(), - READ, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN 1", - Collections.emptyMap(), - ofSeconds(5), - singletonMap("key", valueFactory.value(42)), - database("foo"), - WRITE, - Collections.singleton("neo4j:bookmark:v1:tx1"), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN 1", Collections.emptyMap()), - - // Bolt V3 messages with struct values - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - defaultDatabase(), - READ, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - autoCommitTxRunMessage( - "RETURN $x", - singletonMap("x", valueFactory.value(ZonedDateTime.now())), - ofSeconds(1), - emptyMap(), - database("foo"), - WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory), - unmanagedTxRunMessage("RETURN $x", singletonMap("x", valueFactory.point(42, 1, 2, 3))), - - // New 4.3 Messages - routeMessage(), - // New 5.4 message - telemetryMessage()); - } - - @Override - protected Stream unsupportedMessages() { - return Stream.of( - // Bolt V1, V2 and V3 messages - PULL_ALL, DISCARD_ALL); - } - - private RouteMessage routeMessage() { - Map routeContext = new HashMap<>(); - routeContext.put("someContext", valueFactory.value(124)); - return new RouteMessage(routeContext, Collections.emptySet(), "dbName", null); - } - - private TelemetryMessage telemetryMessage() { - return new TelemetryMessage(1); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v58/BoltProtocolV58Test.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v58/BoltProtocolV58Test.java deleted file mode 100644 index 4d4cf75879..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/messaging/v58/BoltProtocolV58Test.java +++ /dev/null @@ -1,783 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v58; - -import static java.time.Duration.ofSeconds; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.autoCommitTxRunMessage; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RunWithMetadataMessage.unmanagedTxRunMessage; - -import io.netty.channel.embedded.EmbeddedChannel; -import java.time.Clock; -import java.time.Duration; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.mockito.stubbing.Answer; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.connection.ChannelAttributes; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.BeginTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.CommitTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.PullResponseHandlerImpl; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RollbackTxResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.handlers.RunResponseHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.PullMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.BeginMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.CommitMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.HelloMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.LogonMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.RollbackMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.TelemetryMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v57.MessageFormatV57; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public class BoltProtocolV58Test { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private static final String query = "RETURN $x"; - private static final Map query_params = singletonMap("x", value(42)); - private static final long UNLIMITED_FETCH_SIZE = -1; - private static final Duration txTimeout = ofSeconds(12); - private static final Map txMetadata = singletonMap("x", value(42)); - - protected final BoltProtocol protocol = createProtocol(); - private final EmbeddedChannel channel = new EmbeddedChannel(); - private final InboundMessageDispatcher messageDispatcher = - new InboundMessageDispatcher(channel, NoopLoggingProvider.INSTANCE); - - @SuppressWarnings("SameReturnValue") - protected BoltProtocol createProtocol() { - return BoltProtocolV58.INSTANCE; - } - - @BeforeEach - void beforeEach() { - ChannelAttributes.setMessageDispatcher(channel, messageDispatcher); - } - - @AfterEach - void afterEach() { - channel.finishAndReleaseAll(); - } - - @Test - void shouldCreateMessageFormat() { - assertInstanceOf(expectedMessageFormatType(), protocol.createMessageFormat()); - } - - @Test - void shouldInitializeChannel() { - var clock = mock(Clock.class); - var time = 1L; - when(clock.millis()).thenReturn(time); - - var latestAuthMillisFuture = new CompletableFuture(); - - var future = protocol.initializeChannel( - channel, - "MyDriver/0.0.1", - null, - Collections.emptyMap(), - RoutingContext.EMPTY, - null, - clock, - latestAuthMillisFuture, - valueFactory) - .toCompletableFuture(); - - assertEquals(2, channel.outboundMessages().size()); - assertInstanceOf(HelloMessage.class, channel.outboundMessages().poll()); - assertInstanceOf(LogonMessage.class, channel.outboundMessages().poll()); - assertEquals(2, messageDispatcher.queuedHandlersCount()); - assertFalse(future.isDone()); - - var metadata = Map.of( - "server", value("Neo4j/3.5.0"), - "connection_id", value("bolt-42")); - - messageDispatcher.handleSuccessMessage(metadata); - messageDispatcher.handleSuccessMessage(Collections.emptyMap()); - - assertTrue(future.isDone()); - assertEquals(channel, future.join()); - verify(clock).millis(); - assertTrue(latestAuthMillisFuture.isDone()); - assertEquals(time, latestAuthMillisFuture.join()); - } - - @Test - void shouldBeginTransactionWithoutBookmark() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarks() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx100"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - AccessMode.WRITE, - null, - bookmarks, - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - null, - Collections.emptyMap(), - defaultDatabase(), - AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - AccessMode.WRITE, - null, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - txTimeout, - txMetadata, - defaultDatabase(), - AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldBeginTransactionWithBookmarksAndConfig() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var bookmarks = Collections.singleton("neo4j:bookmark:v1:tx4242"); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - AccessMode.WRITE, - null, - bookmarks, - txTimeout, - txMetadata, - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - bookmarks, - txTimeout, - txMetadata, - defaultDatabase(), - AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @Test - void shouldCommitTransaction() { - var bookmarkString = "neo4j:bookmark:v1:tx4242"; - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var commitHandler = (CommitTxResponseHandler) invocation.getArgument(1); - commitHandler.onSuccess(Map.of("bookmark", value(bookmarkString))); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.commitTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(CommitMessage.COMMIT), any(CommitTxResponseHandler.class)); - then(handler).should().onSummary(bookmarkString); - } - - @Test - void shouldRollbackTransaction() { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var rollbackHandler = (RollbackTxResponseHandler) invocation.getArgument(1); - rollbackHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.rollbackTransaction(connection, handler); - - assertEquals(expectedStage, stage); - then(connection).should().write(eq(RollbackMessage.ROLLBACK), any(RollbackTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitWithConfigTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(true, txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForSuccessRunResponse(AccessMode mode) { - testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx65"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse(Collections.emptySet(), null, Collections.emptyMap(), mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInAutoCommitTransactionWithBookmarkAndConfigAndWaitForFailureRunResponse(AccessMode mode) { - testFailedRunInAutoCommitTxWithWaitingForResponse( - Collections.singleton("neo4j:bookmark:v1:tx163"), txTimeout, txMetadata, mode); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldRunInUnmanagedTransactionAndWaitForRunResponse(AccessMode mode) { - testRunAndWaitForRunResponse(false, null, Collections.emptyMap(), mode); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForSuccessRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(true); - } - - @Test - void shouldRunInUnmanagedTransactionAndWaitForFailureRunResponse() { - testRunInUnmanagedTransactionAndWaitForRunResponse(false); - } - - @Test - void databaseNameInBeginTransaction() { - testDatabaseNameSupport(false); - } - - @Test - void databaseNameForAutoCommitTransactions() { - testDatabaseNameSupport(true); - } - - @Test - void shouldSupportDatabaseNameInBeginTransaction() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.beginTransaction( - connection, - database("foo"), - AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldNotSupportDatabaseNameForAutoCommitTransactions() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willReturn(expectedStage); - var future = protocol.runAuto( - connection, - database("foo"), - AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - mock(), - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, future); - then(connection).should().write(any(), any()); - } - - @Test - void shouldTelemetrySendTelemetryMessage() { - var connection = mock(Connection.class); - var expectedStage = CompletableFuture.completedStage(null); - var expectedApi = 1; - given(connection.write(any(), any())).willReturn(expectedStage); - - var future = protocol.telemetry(connection, expectedApi, mock()); - - assertEquals(expectedStage, future); - then(connection).should().write(eq(new TelemetryMessage(expectedApi)), any()); - } - - private Class expectedMessageFormatType() { - return MessageFormatV57.class; - } - - private void testFailedRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, Duration txTimeout, Map txMetadata, AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onFailure(error); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onError(error); - } - - private void testSuccessfulRunInAutoCommitTxWithWaitingForResponse( - Set bookmarks, Duration txTimeout, Map txMetadata, AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedRunStage = CompletableFuture.completedStage(null); - var expectedPullStage = CompletableFuture.completedStage(null); - var newBookmarkValue = "neo4j:bookmark:v1:tx98765"; - given(connection.write(any(), any())) - .willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedRunStage; - }) - .willAnswer((Answer>) invocation -> { - var pullHandler = (PullResponseHandlerImpl) invocation.getArgument(1); - pullHandler.onSuccess(Map.of("has_more", value(false), "bookmark", value(newBookmarkValue))); - return expectedPullStage; - }); - @SuppressWarnings("unchecked") - var runHandler = (MessageHandler) mock(MessageHandler.class); - var pullHandler = mock(PullMessageHandler.class); - - var runStage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - bookmarks, - txTimeout, - txMetadata, - null, - runHandler, - NoopLoggingProvider.INSTANCE, - valueFactory); - var pullStage = protocol.pull(connection, 0, UNLIMITED_FETCH_SIZE, pullHandler, valueFactory); - - assertEquals(expectedRunStage, runStage); - assertEquals(expectedPullStage, pullStage); - var runMessage = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - bookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(runMessage), any(RunResponseHandler.class)); - var pullMessage = new PullMessage(UNLIMITED_FETCH_SIZE, 0L, valueFactory); - then(connection).should().write(eq(pullMessage), any(PullResponseHandlerImpl.class)); - then(runHandler).should().onSummary(any()); - then(pullHandler) - .should() - .onSummary(new PullResponseHandlerImpl.PullSummaryImpl( - false, Map.of("has_more", value(false), "bookmark", value(newBookmarkValue)))); - } - - protected void testRunInUnmanagedTransactionAndWaitForRunResponse(boolean success) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - Throwable error = new RuntimeException(); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - if (success) { - runHandler.onSuccess(emptyMap()); - } else { - runHandler.onFailure(error); - } - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - if (success) { - then(handler).should().onSummary(any()); - } else { - then(handler).should().onError(error); - } - } - - protected void testRunAndWaitForRunResponse( - boolean autoCommitTx, Duration txTimeout, Map txMetadata, AccessMode mode) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - var initialBookmarks = Collections.singleton("neo4j:bookmark:v1:tx987"); - - if (autoCommitTx) { - var stage = protocol.runAuto( - connection, - defaultDatabase(), - mode, - null, - query, - query_params, - initialBookmarks, - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - mode, - initialBookmarks, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - var stage = protocol.run(connection, query, query_params, handler); - - assertEquals(expectedStage, stage); - var message = unmanagedTxRunMessage(query, query_params); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private void testDatabaseNameSupport(boolean autoCommitTx) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - var expectedStage = CompletableFuture.completedStage(null); - if (autoCommitTx) { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var runHandler = (RunResponseHandler) invocation.getArgument(1); - runHandler.onSuccess(Collections.emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.runAuto( - connection, - defaultDatabase(), - AccessMode.WRITE, - null, - query, - query_params, - Collections.emptySet(), - txTimeout, - txMetadata, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - assertEquals(expectedStage, stage); - var message = autoCommitTxRunMessage( - query, - query_params, - txTimeout, - txMetadata, - defaultDatabase(), - AccessMode.WRITE, - Collections.emptySet(), - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(RunResponseHandler.class)); - then(handler).should().onSummary(any()); - } else { - given(connection.write(any(), any())).willAnswer((Answer>) invocation -> { - var beginHandler = (BeginTxResponseHandler) invocation.getArgument(1); - beginHandler.onSuccess(emptyMap()); - return expectedStage; - }); - @SuppressWarnings("unchecked") - var handler = (MessageHandler) mock(MessageHandler.class); - - var stage = protocol.beginTransaction( - connection, - defaultDatabase(), - AccessMode.WRITE, - null, - Collections.emptySet(), - null, - Collections.emptyMap(), - null, - null, - handler, - NoopLoggingProvider.INSTANCE, - valueFactory); - - assertEquals(expectedStage, stage); - var message = new BeginMessage( - Collections.emptySet(), - null, - Collections.emptyMap(), - defaultDatabase(), - AccessMode.WRITE, - null, - null, - null, - false, - NoopLoggingProvider.INSTANCE, - valueFactory); - then(connection).should().write(eq(message), any(BeginTxResponseHandler.class)); - then(handler).should().onSummary(any()); - } - } - - private static Value value(Object value) { - return valueFactory.value(value); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/packstream/PackStreamTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/packstream/PackStreamTest.java deleted file mode 100644 index df6f6389f7..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/packstream/PackStreamTest.java +++ /dev/null @@ -1,742 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.packstream; - -import static java.util.Arrays.asList; -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.channels.Channels; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import org.junit.jupiter.api.Test; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.io.BufferedChannelInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.io.ChannelOutput; - -public class PackStreamTest { - public static Map asMap(Object... keysAndValues) { - Map map = new LinkedHashMap<>(keysAndValues.length / 2); - String key = null; - for (var keyOrValue : keysAndValues) { - if (key == null) { - key = keyOrValue.toString(); - } else { - map.put(key, keyOrValue); - key = null; - } - } - return map; - } - - private static class Machine { - - private final ByteArrayOutputStream output; - private final PackStream.Packer packer; - - Machine() { - this.output = new ByteArrayOutputStream(); - this.packer = new PackStream.Packer(new ChannelOutput(Channels.newChannel(this.output))); - } - - public void reset() { - output.reset(); - } - - public byte[] output() { - return output.toByteArray(); - } - - PackStream.Packer packer() { - return packer; - } - } - - private PackStream.Unpacker newUnpacker(byte[] bytes) { - var input = new ByteArrayInputStream(bytes); - return new PackStream.Unpacker(new BufferedChannelInput(Channels.newChannel(input))); - } - - @Test - void testCanPackAndUnpackNull() throws Throwable { - // Given - var machine = new Machine(); - - // When - machine.packer().packNull(); - - // Then - var bytes = machine.output(); - assertArrayEquals(new byte[] {(byte) 0xC0}, bytes); - - // When - var unpacker = newUnpacker(bytes); - var packType = unpacker.peekNextType(); - - // Then - assertEquals(PackType.NULL, packType); - } - - @Test - void testCanPackAndUnpackTrue() throws Throwable { - // Given - var machine = new Machine(); - - // When - machine.packer().pack(true); - - // Then - var bytes = machine.output(); - assertArrayEquals(new byte[] {(byte) 0xC3}, bytes); - - // When - var unpacker = newUnpacker(bytes); - var packType = unpacker.peekNextType(); - - // Then - assertEquals(PackType.BOOLEAN, packType); - assertTrue(unpacker.unpackBoolean()); - } - - @Test - void testCanPackAndUnpackFalse() throws Throwable { - // Given - var machine = new Machine(); - - // When - machine.packer().pack(false); - - // Then - var bytes = machine.output(); - assertArrayEquals(new byte[] {(byte) 0xC2}, bytes); - - // When - var unpacker = newUnpacker(bytes); - var packType = unpacker.peekNextType(); - - // Then - assertEquals(PackType.BOOLEAN, packType); - assertFalse(unpacker.unpackBoolean()); - } - - @Test - void testCanPackAndUnpackTinyIntegers() throws Throwable { - // Given - var machine = new Machine(); - - for (long i = -16; i < 128; i++) { - // When - machine.reset(); - machine.packer().pack(i); - - // Then - var bytes = machine.output(); - assertEquals(1, bytes.length); - - // When - var unpacker = newUnpacker(bytes); - var packType = unpacker.peekNextType(); - - // Then - assertEquals(PackType.INTEGER, packType); - assertEquals(i, unpacker.unpackLong()); - } - } - - @Test - void testCanPackAndUnpackShortIntegers() throws Throwable { - // Given - var machine = new Machine(); - - for (long i = -32768; i < 32768; i++) { - // When - machine.reset(); - machine.packer().pack(i); - - // Then - var bytes = machine.output(); - assertTrue(bytes.length <= 3); - - // When - var unpacker = newUnpacker(bytes); - var packType = unpacker.peekNextType(); - - // Then - assertEquals(PackType.INTEGER, packType); - assertEquals(i, unpacker.unpackLong()); - } - } - - @Test - void testCanPackAndUnpackPowersOfTwoAsIntegers() throws Throwable { - // Given - var machine = new Machine(); - - for (var i = 0; i < 32; i++) { - var n = (long) Math.pow(2, i); - - // When - machine.reset(); - machine.packer().pack(n); - - // Then - var unpacker = newUnpacker(machine.output()); - var packType = unpacker.peekNextType(); - - // Then - assertEquals(PackType.INTEGER, packType); - assertEquals(n, unpacker.unpackLong()); - } - } - - @Test - void testCanPackAndUnpackPowersOfTwoPlusABitAsDoubles() throws Throwable { - // Given - var machine = new Machine(); - - for (var i = 0; i < 32; i++) { - var n = Math.pow(2, i) + 0.5; - - // When - machine.reset(); - machine.packer().pack(n); - - // Then - var unpacker = newUnpacker(machine.output()); - var packType = unpacker.peekNextType(); - - // Then - assertEquals(PackType.FLOAT, packType); - assertEquals(n, unpacker.unpackDouble()); - } - } - - @Test - void testCanPackAndUnpackPowersOfTwoMinusABitAsDoubles() throws Throwable { - // Given - var machine = new Machine(); - - for (var i = 0; i < 32; i++) { - var n = Math.pow(2, i) - 0.5; - - // When - machine.reset(); - machine.packer().pack(n); - - // Then - var unpacker = newUnpacker(machine.output()); - var packType = unpacker.peekNextType(); - - // Then - assertEquals(PackType.FLOAT, packType); - assertEquals(n, unpacker.unpackDouble()); - } - } - - @Test - void testCanPackAndUnpackByteArrays() throws Throwable { - // Given - var machine = new Machine(); - - testByteArrayPackingAndUnpacking(machine, 0); - for (var i = 0; i < 24; i++) { - testByteArrayPackingAndUnpacking(machine, (int) Math.pow(2, i)); - } - } - - private void testByteArrayPackingAndUnpacking(Machine machine, int length) throws Throwable { - var array = new byte[length]; - - machine.reset(); - machine.packer().pack(array); - - var unpacker = newUnpacker(machine.output()); - var packType = unpacker.peekNextType(); - - assertEquals(PackType.BYTES, packType); - assertArrayEquals(array, unpacker.unpackBytes()); - } - - @Test - void testCanPackAndUnpackStrings() throws Throwable { - // Given - var machine = new Machine(); - - for (var i = 0; i < 24; i++) { - var string = new String(new byte[(int) Math.pow(2, i)]); - - // When - machine.reset(); - machine.packer().pack(string); - - // Then - var unpacker = newUnpacker(machine.output()); - var packType = unpacker.peekNextType(); - - // Then - assertEquals(PackType.STRING, packType); - assertEquals(string, unpacker.unpackString()); - } - } - - @Test - void testCanPackAndUnpackBytes() throws Throwable { - // Given - var machine = new Machine(); - - // When - var packer = machine.packer(); - packer.pack("ABCDEFGHIJ".getBytes()); - - // Then - var unpacker = newUnpacker(machine.output()); - var packType = unpacker.peekNextType(); - - // Then - assertEquals(PackType.BYTES, packType); - assertArrayEquals("ABCDEFGHIJ".getBytes(), unpacker.unpackBytes()); - } - - @Test - void testCanPackAndUnpackString() throws Throwable { - // Given - var machine = new Machine(); - - // When - var packer = machine.packer(); - packer.pack("ABCDEFGHIJ"); - - // Then - var unpacker = newUnpacker(machine.output()); - var packType = unpacker.peekNextType(); - - // Then - assertEquals(PackType.STRING, packType); - assertEquals("ABCDEFGHIJ", unpacker.unpackString()); - } - - @Test - void testCanPackAndUnpackSpecialString() throws Throwable { - // Given - var machine = new Machine(); - var code = "Mjölnir"; - - // When - var packer = machine.packer(); - packer.pack(code); - - // Then - var unpacker = newUnpacker(machine.output()); - var packType = unpacker.peekNextType(); - - // Then - assertEquals(PackType.STRING, packType); - assertEquals(code, unpacker.unpackString()); - } - - @Test - void testCanPackAndUnpackListOneItemAtATime() throws Throwable { - // Given - var machine = new Machine(); - - // When - var packer = machine.packer(); - packer.packListHeader(3); - packer.pack(12); - packer.pack(13); - packer.pack(14); - - // Then - var unpacker = newUnpacker(machine.output()); - var packType = unpacker.peekNextType(); - - assertEquals(PackType.LIST, packType); - assertEquals(3L, unpacker.unpackListHeader()); - assertEquals(12L, unpacker.unpackLong()); - assertEquals(13L, unpacker.unpackLong()); - assertEquals(14L, unpacker.unpackLong()); - } - - @Test - void testCanPackAndUnpackListOfString() throws Throwable { - // Given - var machine = new Machine(); - - // When - var packer = machine.packer(); - packer.pack(asList("eins", "zwei", "drei")); - - // Then - var unpacker = newUnpacker(machine.output()); - var packType = unpacker.peekNextType(); - - assertEquals(PackType.LIST, packType); - assertEquals(3L, unpacker.unpackListHeader()); - assertEquals("eins", unpacker.unpackString()); - assertEquals("zwei", unpacker.unpackString()); - assertEquals("drei", unpacker.unpackString()); - } - - @Test - void testCanPackAndUnpackListOfSpecialStrings() throws Throwable { - assertPackStringLists(3); - assertPackStringLists(126); - assertPackStringLists(3000); - assertPackStringLists(32768); - } - - @Test - void testCanPackAndUnpackListOfStringOneByOne() throws Throwable { - // Given - var machine = new Machine(); - - // When - var packer = machine.packer(); - packer.packListHeader(3); - packer.pack("eins"); - packer.pack("zwei"); - packer.pack("drei"); - - // Then - var unpacker = newUnpacker(machine.output()); - var packType = unpacker.peekNextType(); - - assertEquals(PackType.LIST, packType); - assertEquals(3L, unpacker.unpackListHeader()); - assertEquals("eins", unpacker.unpackString()); - assertEquals("zwei", unpacker.unpackString()); - assertEquals("drei", unpacker.unpackString()); - } - - @Test - void testCanPackAndUnpackListOfSpecialStringOneByOne() throws Throwable { - // Given - var machine = new Machine(); - - // When - var packer = machine.packer(); - packer.packListHeader(3); - packer.pack("Mjölnir"); - packer.pack("Mjölnir"); - packer.pack("Mjölnir"); - - // Then - var unpacker = newUnpacker(machine.output()); - var packType = unpacker.peekNextType(); - - assertEquals(PackType.LIST, packType); - assertEquals(3L, unpacker.unpackListHeader()); - assertEquals("Mjölnir", unpacker.unpackString()); - assertEquals("Mjölnir", unpacker.unpackString()); - assertEquals("Mjölnir", unpacker.unpackString()); - } - - @Test - void testCanPackAndUnpackMap() throws Throwable { - assertMap(2); - assertMap(126); - assertMap(2439); - assertMap(32768); - } - - @Test - void testCanPackAndUnpackStruct() throws Throwable { - // Given - var machine = new Machine(); - - // When - var packer = machine.packer(); - packer.packStructHeader(3, (byte) 'N'); - packer.pack(12); - packer.pack(asList("Person", "Employee")); - packer.pack(asMap("name", "Alice", "age", 33)); - - // Then - var unpacker = newUnpacker(machine.output()); - var packType = unpacker.peekNextType(); - - assertEquals(PackType.STRUCT, packType); - assertEquals(3L, unpacker.unpackStructHeader()); - assertEquals((byte) 'N', unpacker.unpackStructSignature()); - - assertEquals(12L, unpacker.unpackLong()); - - assertEquals(2L, unpacker.unpackListHeader()); - assertEquals("Person", unpacker.unpackString()); - assertEquals("Employee", unpacker.unpackString()); - - assertEquals(2L, unpacker.unpackMapHeader()); - assertEquals("name", unpacker.unpackString()); - assertEquals("Alice", unpacker.unpackString()); - assertEquals("age", unpacker.unpackString()); - assertEquals(33L, unpacker.unpackLong()); - } - - @Test - void testCanPackAndUnpackStructsOfDifferentSizes() throws Throwable { - assertStruct(2); - assertStruct(126); - assertStruct(2439); - - // we cannot have 'too many' fields - assertThrows(PackStream.Overflow.class, () -> assertStruct(65536)); - } - - @Test - void testCanDoStreamingListUnpacking() throws Throwable { - // Given - var machine = new Machine(); - var packer = machine.packer(); - packer.pack(asList(1, 2, 3, asList(4, 5))); - - // When I unpack this value - var unpacker = newUnpacker(machine.output()); - - // Then I can do streaming unpacking - var size = unpacker.unpackListHeader(); - var a = unpacker.unpackLong(); - var b = unpacker.unpackLong(); - var c = unpacker.unpackLong(); - - var innerSize = unpacker.unpackListHeader(); - var d = unpacker.unpackLong(); - var e = unpacker.unpackLong(); - - // And all the values should be sane - assertEquals(4, size); - assertEquals(2, innerSize); - assertEquals(1, a); - assertEquals(2, b); - assertEquals(3, c); - assertEquals(4, d); - assertEquals(5, e); - } - - @Test - void testCanDoStreamingStructUnpacking() throws Throwable { - // Given - var machine = new Machine(); - var packer = machine.packer(); - packer.packStructHeader(4, (byte) '~'); - packer.pack(1); - packer.pack(2); - packer.pack(3); - packer.pack(asList(4, 5)); - - // When I unpack this value - var unpacker = newUnpacker(machine.output()); - - // Then I can do streaming unpacking - var size = unpacker.unpackStructHeader(); - var signature = unpacker.unpackStructSignature(); - var a = unpacker.unpackLong(); - var b = unpacker.unpackLong(); - var c = unpacker.unpackLong(); - - var innerSize = unpacker.unpackListHeader(); - var d = unpacker.unpackLong(); - var e = unpacker.unpackLong(); - - // And all the values should be sane - assertEquals(4, size); - assertEquals('~', signature); - assertEquals(2, innerSize); - assertEquals(1, a); - assertEquals(2, b); - assertEquals(3, c); - assertEquals(4, d); - assertEquals(5, e); - } - - @Test - void testCanDoStreamingMapUnpacking() throws Throwable { - // Given - var machine = new Machine(); - var packer = machine.packer(); - packer.packMapHeader(2); - packer.pack("name"); - packer.pack("Bob"); - packer.pack("cat_ages"); - packer.pack(asList(4.3, true)); - - // When I unpack this value - var unpacker = newUnpacker(machine.output()); - - // Then I can do streaming unpacking - var size = unpacker.unpackMapHeader(); - var k1 = unpacker.unpackString(); - var v1 = unpacker.unpackString(); - var k2 = unpacker.unpackString(); - - var innerSize = unpacker.unpackListHeader(); - var d = unpacker.unpackDouble(); - var e = unpacker.unpackBoolean(); - - // And all the values should be sane - assertEquals(2, size); - assertEquals(2, innerSize); - assertEquals("name", k1); - assertEquals("Bob", v1); - assertEquals("cat_ages", k2); - assertEquals(4.3, d, 0.0001); - assertTrue(e); - } - - @Test - void handlesDataCrossingBufferBoundaries() throws Throwable { - // Given - var machine = new Machine(); - var packer = machine.packer(); - packer.pack(Long.MAX_VALUE); - packer.pack(Long.MAX_VALUE); - - var ch = Channels.newChannel(new ByteArrayInputStream(machine.output())); - var unpacker = new PackStream.Unpacker(new BufferedChannelInput(11, ch)); - - // Serialized ch will look like, and misalign with the 11-byte unpack buffer: - - // [XX][XX][XX][XX][XX][XX][XX][XX][XX][XX][XX][XX][XX][XX][XX][XX][XX][XX] - // mkr \___________data______________/ mkr \___________data______________/ - // \____________unpack buffer_________________/ - - // When - var first = unpacker.unpackLong(); - var second = unpacker.unpackLong(); - - // Then - assertEquals(Long.MAX_VALUE, first); - assertEquals(Long.MAX_VALUE, second); - } - - @Test - void testCanPeekOnNextType() throws Throwable { - // When & Then - assertPeekType(PackType.STRING, "a string"); - assertPeekType(PackType.INTEGER, 123); - assertPeekType(PackType.FLOAT, 123.123); - assertPeekType(PackType.BOOLEAN, true); - assertPeekType(PackType.LIST, asList(1, 2, 3)); - assertPeekType(PackType.MAP, asMap("l", 3)); - } - - @Test - void shouldFailForUnknownValue() { - // Given - var machine = new Machine(); - var packer = machine.packer(); - - // Expect - assertThrows(PackStream.UnPackable.class, () -> packer.pack(new MyRandomClass())); - } - - private static class MyRandomClass {} - - private void assertPeekType(PackType type, Object value) throws IOException { - // Given - var machine = new Machine(); - var packer = machine.packer(); - packer.pack(value); - - var unpacker = newUnpacker(machine.output()); - - // When & Then - assertEquals(type, unpacker.peekNextType()); - } - - private void assertPackStringLists(int size) throws Throwable { - // Given - var machine = new Machine(); - - // When - var packer = machine.packer(); - var strings = new ArrayList(size); - for (var i = 0; i < size; i++) { - strings.add(i, "Mjölnir"); - } - packer.pack(strings); - - // Then - var unpacker = newUnpacker(machine.output()); - var packType = unpacker.peekNextType(); - assertEquals(PackType.LIST, packType); - - assertEquals(size, unpacker.unpackListHeader()); - for (var i = 0; i < size; i++) { - assertEquals("Mjölnir", unpacker.unpackString()); - } - } - - private void assertMap(int size) throws Throwable { - // Given - var machine = new Machine(); - - // When - var packer = machine.packer(); - var map = IntStream.range(0, size) - .boxed() - .collect(Collectors.toMap(i -> Integer.toString(i), Function.identity(), (a, b) -> b, HashMap::new)); - packer.pack(map); - - // Then - var unpacker = newUnpacker(machine.output()); - var packType = unpacker.peekNextType(); - - assertEquals(PackType.MAP, packType); - - assertEquals(size, unpacker.unpackMapHeader()); - - for (var i = 0; i < size; i++) { - var v = unpacker.unpackString(); - var n = unpacker.unpackLong(); - assertEquals(Long.toString(n), v); - } - } - - private void assertStruct(int size) throws Throwable { - // Given - var machine = new Machine(); - - // When - var packer = machine.packer(); - packer.packStructHeader(size, (byte) 'N'); - for (var i = 0; i < size; i++) { - packer.pack(i); - } - - // Then - var unpacker = newUnpacker(machine.output()); - var packType = unpacker.peekNextType(); - - assertEquals(PackType.STRUCT, packType); - assertEquals(size, unpacker.unpackStructHeader()); - assertEquals((byte) 'N', unpacker.unpackStructSignature()); - - for (var i = 0; i < size; i++) { - assertEquals(i, unpacker.unpackLong()); - } - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/MetadataExtractorTest.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/MetadataExtractorTest.java deleted file mode 100644 index 9275442fc1..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/MetadataExtractorTest.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.util; - -import static java.util.Arrays.asList; -import static java.util.Collections.emptyList; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.neo4j.driver.internal.bolt.basicimpl.impl.util.MetadataExtractor.extractServer; - -import org.junit.jupiter.api.Test; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.exception.BoltUntrustedServerException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; - -class MetadataExtractorTest { - private static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - private static final String RESULT_AVAILABLE_AFTER_KEY = "available_after"; - - private final MetadataExtractor extractor = new MetadataExtractor(RESULT_AVAILABLE_AFTER_KEY); - - @Test - void shouldExtractQueryKeys() { - var keys = asList("hello", " ", "world", "!"); - - var extracted = extractor.extractQueryKeys(singletonMap("fields", valueFactory.value(keys))); - assertEquals(keys, extracted); - } - - @Test - void shouldExtractEmptyQueryKeysWhenNoneInMetadata() { - var extracted = extractor.extractQueryKeys(emptyMap()); - assertEquals(emptyList(), extracted); - } - - @Test - void shouldExtractResultAvailableAfter() { - var metadata = singletonMap(RESULT_AVAILABLE_AFTER_KEY, valueFactory.value(424242)); - var extractedResultAvailableAfter = extractor.extractResultAvailableAfter(metadata); - assertEquals(424242L, extractedResultAvailableAfter); - } - - @Test - void shouldExtractNoResultAvailableAfterWhenNoneInMetadata() { - var extractedResultAvailableAfter = extractor.extractResultAvailableAfter(emptyMap()); - assertEquals(-1, extractedResultAvailableAfter); - } - - @Test - void shouldExtractServer() { - var agent = "Neo4j/3.5.0"; - var metadata = singletonMap("server", valueFactory.value(agent)); - - var serverValue = extractServer(metadata); - - assertEquals(agent, serverValue.asString()); - } - - @Test - void shouldFailToExtractServerVersionWhenMetadataDoesNotContainIt() { - assertThrows( - BoltUntrustedServerException.class, - () -> extractServer(singletonMap("server", valueFactory.value(null)))); - assertThrows(BoltUntrustedServerException.class, () -> extractServer(singletonMap("server", null))); - } - - @Test - void shouldFailToExtractServerVersionFromNonNeo4jProduct() { - assertThrows( - BoltUntrustedServerException.class, - () -> extractServer(singletonMap("server", valueFactory.value("NotNeo4j/1.2.3")))); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/TestUtil.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/TestUtil.java deleted file mode 100644 index 67a7506dc3..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/TestUtil.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.util; - -import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static java.util.concurrent.TimeUnit.MINUTES; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; - -import io.netty.buffer.ByteBuf; -import io.netty.util.internal.PlatformDependent; -import java.util.Arrays; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeoutException; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.BoltProtocol; -import org.neo4j.driver.internal.bolt.basicimpl.impl.spi.Connection; - -public class TestUtil { - private static final long DEFAULT_WAIT_TIME_MS = MINUTES.toMillis(100); - - public static Connection connectionMock(BoltProtocol protocol) { - var connection = mock(Connection.class); - given(connection.protocol()).willReturn(protocol); - return connection; - } - - public static void assertByteBufEquals(ByteBuf expected, ByteBuf actual) { - try { - assertEquals(expected, actual); - } finally { - releaseIfPossible(expected); - releaseIfPossible(actual); - } - } - - public static T await(CompletableFuture future) { - return await((Future) future); - } - - public static > T await(U future) { - try { - return future.get(DEFAULT_WAIT_TIME_MS, MILLISECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new AssertionError("Interrupted while waiting for future: " + future, e); - } catch (ExecutionException e) { - PlatformDependent.throwException(e.getCause()); - return null; - } catch (TimeoutException e) { - throw new AssertionError("Given future did not complete in time: " + future); - } - } - - public static void assertByteBufContains(ByteBuf buf, Number... values) { - try { - assertNotNull(buf); - var expectedReadableBytes = - Arrays.stream(values).mapToInt(TestUtil::bytesCount).sum(); - assertEquals(expectedReadableBytes, buf.readableBytes(), "Unexpected number of bytes"); - for (var expectedValue : values) { - var actualValue = read(buf, expectedValue.getClass()); - var valueType = actualValue.getClass().getSimpleName(); - assertEquals(expectedValue, actualValue, valueType + " values not equal"); - } - } finally { - releaseIfPossible(buf); - } - } - - private static Number read(ByteBuf buf, Class type) { - if (type == Byte.class) { - return buf.readByte(); - } else if (type == Short.class) { - return buf.readShort(); - } else if (type == Integer.class) { - return buf.readInt(); - } else if (type == Long.class) { - return buf.readLong(); - } else if (type == Float.class) { - return buf.readFloat(); - } else if (type == Double.class) { - return buf.readDouble(); - } else { - throw new IllegalArgumentException("Unexpected numeric type: " + type); - } - } - - private static int bytesCount(Number value) { - if (value instanceof Byte) { - return 1; - } else if (value instanceof Short) { - return 2; - } else if (value instanceof Integer) { - return 4; - } else if (value instanceof Long) { - return 8; - } else if (value instanceof Float) { - return 4; - } else if (value instanceof Double) { - return 8; - } else { - throw new IllegalArgumentException("Unexpected number: '" + value + "' or type" + value.getClass()); - } - } - - private static void releaseIfPossible(ByteBuf buf) { - if (buf.refCnt() > 0) { - buf.release(); - } - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/io/BufferedChannelInput.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/io/BufferedChannelInput.java deleted file mode 100644 index 0d1aae082b..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/io/BufferedChannelInput.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.util.io; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.ReadableByteChannel; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackStream; - -/** - * An {@link PackInput} implementation that reads from an input channel into an internal buffer. - */ -public class BufferedChannelInput implements PackInput { - private final ByteBuffer buffer; - private final ReadableByteChannel channel; - private static final int DEFAULT_BUFFER_CAPACITY = 8192; - - public BufferedChannelInput(ReadableByteChannel ch) { - this(DEFAULT_BUFFER_CAPACITY, ch); - } - - public BufferedChannelInput(int bufferCapacity, ReadableByteChannel ch) { - this.buffer = ByteBuffer.allocate(bufferCapacity).order(ByteOrder.BIG_ENDIAN); - this.buffer.limit(0); - this.channel = ch; - } - - @Override - public byte readByte() throws IOException { - ensure(1); - return buffer.get(); - } - - @Override - public short readShort() throws IOException { - ensure(2); - return buffer.getShort(); - } - - @Override - public int readInt() throws IOException { - ensure(4); - return buffer.getInt(); - } - - @Override - public long readLong() throws IOException { - ensure(8); - return buffer.getLong(); - } - - @Override - public double readDouble() throws IOException { - ensure(8); - return buffer.getDouble(); - } - - @Override - public void readBytes(byte[] into, int index, int toRead) throws IOException { - var endIndex = index + toRead; - while (index < endIndex) { - toRead = Math.min(buffer.remaining(), endIndex - index); - buffer.get(into, index, toRead); - index += toRead; - if (buffer.remaining() == 0 && index < endIndex) { - attempt(endIndex - index); - if (buffer.remaining() == 0) { - throw new PackStream.EndOfStream("Expected " + (endIndex - index) + " bytes available, " - + "but no more bytes accessible from underlying stream."); - } - } - } - } - - @Override - public byte peekByte() throws IOException { - ensure(1); - return buffer.get(buffer.position()); - } - - private boolean attempt(int numBytes) throws IOException { - if (buffer.remaining() >= numBytes) { - return true; - } - - if (buffer.remaining() > 0) { - // If there is data remaining in the buffer, shift that remaining data to the beginning of the buffer. - buffer.compact(); - } else { - buffer.clear(); - } - - int count; - do { - count = channel.read(buffer); - } while (count >= 0 && (buffer.position() < numBytes && buffer.remaining() != 0)); - - buffer.flip(); - return buffer.remaining() >= numBytes; - } - - private void ensure(int numBytes) throws IOException { - if (!attempt(numBytes)) { - throw new PackStream.EndOfStream("Unexpected end of stream while trying to read " + numBytes + " bytes."); - } - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/io/ByteBufOutput.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/io/ByteBufOutput.java deleted file mode 100644 index 9381b5ef1a..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/io/ByteBufOutput.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.util.io; - -import io.netty.buffer.ByteBuf; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -public class ByteBufOutput implements PackOutput { - private final ByteBuf buf; - - public ByteBufOutput(ByteBuf buf) { - this.buf = buf; - } - - @Override - public PackOutput writeByte(byte value) { - buf.writeByte(value); - return this; - } - - @Override - public PackOutput writeBytes(byte[] data) { - buf.writeBytes(data); - return this; - } - - @Override - public PackOutput writeShort(short value) { - buf.writeShort(value); - return this; - } - - @Override - public PackOutput writeInt(int value) { - buf.writeInt(value); - return this; - } - - @Override - public PackOutput writeLong(long value) { - buf.writeLong(value); - return this; - } - - @Override - public PackOutput writeDouble(double value) { - buf.writeDouble(value); - return this; - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/io/ChannelOutput.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/io/ChannelOutput.java deleted file mode 100644 index 6c6d76a75b..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/io/ChannelOutput.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.util.io; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.WritableByteChannel; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -public class ChannelOutput implements PackOutput { - private final WritableByteChannel channel; - - public ChannelOutput(WritableByteChannel channel) { - this.channel = channel; - } - - @Override - public PackOutput writeBytes(byte[] data) throws IOException { - channel.write(ByteBuffer.wrap(data)); - return this; - } - - @Override - public PackOutput writeByte(byte value) throws IOException { - channel.write(ByteBuffer.wrap(new byte[] {value})); - return this; - } - - @Override - public PackOutput writeShort(short value) throws IOException { - var buffer = ByteBuffer.allocate(Short.BYTES); - buffer.putShort(value); - buffer.flip(); - channel.write(buffer); - return this; - } - - @Override - public PackOutput writeInt(int value) throws IOException { - var buffer = ByteBuffer.allocate(Integer.BYTES); - buffer.putInt(value); - buffer.flip(); - channel.write(buffer); - return this; - } - - @Override - public PackOutput writeLong(long value) throws IOException { - var buffer = ByteBuffer.allocate(Long.BYTES); - buffer.putLong(value); - buffer.flip(); - channel.write(buffer); - return this; - } - - @Override - public PackOutput writeDouble(double value) throws IOException { - var buffer = ByteBuffer.allocate(Double.BYTES); - buffer.putDouble(value); - buffer.flip(); - channel.write(buffer); - return this; - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/io/MessageToByteBufWriter.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/io/MessageToByteBufWriter.java deleted file mode 100644 index 2ed4b5ddc5..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/io/MessageToByteBufWriter.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.util.io; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import java.io.IOException; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; - -public class MessageToByteBufWriter { - private final MessageFormat messageFormat; - - public MessageToByteBufWriter(MessageFormat messageFormat) { - this.messageFormat = messageFormat; - } - - public ByteBuf asByteBuf(Message message) { - try { - var buf = Unpooled.buffer(); - var output = new ByteBufOutput(buf); - messageFormat.newWriter(output, TestValueFactory.INSTANCE).write(message); - return buf; - } catch (IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/AbstractMessageReaderTestBase.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/AbstractMessageReaderTestBase.java deleted file mode 100644 index 6cfab936ff..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/AbstractMessageReaderTestBase.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.fail; -import static org.junit.jupiter.api.DynamicTest.dynamicTest; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -import io.netty.buffer.Unpooled; -import java.io.IOException; -import java.util.stream.Stream; -import org.junit.jupiter.api.DynamicNode; -import org.junit.jupiter.api.TestFactory; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.GqlErrorUtil; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.ByteBufInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ResponseMessageHandler; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.FailureMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.IgnoredMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.RecordMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.SuccessMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.io.ByteBufOutput; - -public abstract class AbstractMessageReaderTestBase { - protected static final TestValueFactory valueFactory = TestValueFactory.INSTANCE; - - @TestFactory - Stream shouldReadSupportedMessages() { - return supportedMessages() - .map(message -> dynamicTest(message.toString(), () -> testSupportedMessageReading(message))); - } - - private void testSupportedMessageReading(Message message) throws IOException { - var handler = testMessageReading(message); - - if (message instanceof SuccessMessage successMessage) { - verify(handler).handleSuccessMessage(successMessage.metadata()); - } else if (message instanceof FailureMessage failureMessage) { - verify(handler) - .handleFailureMessage(GqlErrorUtil.gqlError(failureMessage.code(), failureMessage.message())); - } else if (message instanceof IgnoredMessage) { - verify(handler).handleIgnoredMessage(); - } else if (message instanceof RecordMessage recordMessage) { - verify(handler).handleRecordMessage(recordMessage.fields()); - } else { - fail("Unsupported message type " + message.getClass().getSimpleName()); - } - } - - @TestFactory - Stream shouldFailToReadUnsupportedMessages() { - return unsupportedMessages() - .map(message -> dynamicTest(message.toString(), () -> testUnsupportedMessageReading(message))); - } - - private void testUnsupportedMessageReading(Message message) { - assertThrows(IOException.class, () -> testMessageReading(message)); - } - - protected abstract Stream supportedMessages(); - - protected abstract Stream unsupportedMessages(); - - protected abstract MessageFormat.Reader newReader(PackInput input); - - protected ResponseMessageHandler testMessageReading(Message message) throws IOException { - var input = newInputWith(message); - var reader = newReader(input); - - var handler = mock(ResponseMessageHandler.class); - reader.read(handler); - - return handler; - } - - private PackInput newInputWith(Message message) throws IOException { - var buffer = Unpooled.buffer(); - - MessageFormat messageFormat = new KnowledgeableMessageFormat(isElementIdEnabled()); - if (isDateTimeUtcEnabled()) { - messageFormat.enableDateTimeUtc(); - } - var writer = messageFormat.newWriter(new ByteBufOutput(buffer), TestValueFactory.INSTANCE); - writer.write(message); - - var input = new ByteBufInput(); - input.start(buffer); - return input; - } - - protected boolean isElementIdEnabled() { - return false; - } - - protected boolean isDateTimeUtcEnabled() { - return false; - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/AbstractMessageWriterTestBase.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/AbstractMessageWriterTestBase.java deleted file mode 100644 index de76ba00f5..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/AbstractMessageWriterTestBase.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.DynamicTest.dynamicTest; -import static org.mockito.Mockito.mock; - -import io.netty.buffer.Unpooled; -import java.io.IOException; -import java.util.stream.Stream; -import org.junit.jupiter.api.DynamicNode; -import org.junit.jupiter.api.TestFactory; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.ByteBufInput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageFormat; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackStream; -import org.neo4j.driver.internal.bolt.basicimpl.impl.util.io.ByteBufOutput; - -public abstract class AbstractMessageWriterTestBase { - protected static final ValueFactory valueFactory = TestValueFactory.INSTANCE; - - @TestFactory - Stream shouldWriteSupportedMessages() { - return supportedMessages() - .map(message -> dynamicTest(message.toString(), () -> testSupportedMessageWriting(message))); - } - - @TestFactory - Stream shouldFailToWriteUnsupportedMessages() { - return unsupportedMessages() - .map(message -> dynamicTest(message.toString(), () -> testUnsupportedMessageWriting(message))); - } - - protected abstract MessageFormat.Writer newWriter(PackOutput output); - - protected abstract Stream supportedMessages(); - - protected abstract Stream unsupportedMessages(); - - private void testSupportedMessageWriting(Message message) throws IOException { - var buffer = Unpooled.buffer(); - PackOutput output = new ByteBufOutput(buffer); - - var writer = newWriter(output); - writer.write(message); - - var input = new ByteBufInput(); - input.start(buffer); - var unpacker = new PackStream.Unpacker(input); - - var structHeader = unpacker.unpackStructHeader(); - assertTrue(structHeader >= 0L); - - var structSignature = unpacker.unpackStructSignature(); - assertEquals(message.signature(), structSignature); - } - - private void testUnsupportedMessageWriting(Message message) { - var writer = newWriter(mock(PackOutput.class)); - assertThrows(Exception.class, () -> writer.write(message)); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/FailureMessageEncoder.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/FailureMessageEncoder.java deleted file mode 100644 index 925938f8fa..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/FailureMessageEncoder.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.FailureMessage; - -public class FailureMessageEncoder implements MessageEncoder { - @Override - public void encode(Message message, ValuePacker packer, ValueFactory valueFactory) throws IOException { - var failureMessage = (FailureMessage) message; - packer.packStructHeader(1, failureMessage.signature()); - Map body = new HashMap<>(); - body.put("code", valueFactory.value(failureMessage.code())); - body.put("message", valueFactory.value(failureMessage.message())); - packer.pack(body); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/IgnoredMessageEncoder.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/IgnoredMessageEncoder.java deleted file mode 100644 index 56c40eb700..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/IgnoredMessageEncoder.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging; - -import java.io.IOException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.IgnoredMessage; - -public class IgnoredMessageEncoder implements MessageEncoder { - @Override - public void encode(Message message, ValuePacker packer, ValueFactory valueFactory) throws IOException { - packer.packStructHeader(0, IgnoredMessage.SIGNATURE); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/KnowledgeableMessageFormat.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/KnowledgeableMessageFormat.java deleted file mode 100644 index 418583f7ea..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/KnowledgeableMessageFormat.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging; - -import java.io.IOException; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.stream.StreamSupport; -import org.neo4j.bolt.api.test.values.TestNode; -import org.neo4j.bolt.api.test.values.TestPath; -import org.neo4j.bolt.api.test.values.TestRelationship; -import org.neo4j.bolt.api.test.values.TestValue; -import org.neo4j.bolt.api.test.values.TestValueFactory; -import org.neo4j.bolt.api.test.values.impl.Entity; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.AbstractMessageWriter; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.common.CommonValueUnpacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.DiscardAllMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.PullAllMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.encode.ResetMessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.DiscardAllMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.PullAllMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.request.ResetMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.FailureMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.IgnoredMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.RecordMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.SuccessMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.v3.MessageFormatV3; -import org.neo4j.driver.internal.bolt.basicimpl.impl.packstream.PackOutput; - -/** - * This class provides the missing server side packing methods to serialize Node, Relationship and Path. It also allows writing of server side messages like - * SUCCESS, FAILURE, IGNORED and RECORD. - */ -public class KnowledgeableMessageFormat extends MessageFormatV3 { - private final boolean elementIdEnabled; - private boolean dateTimeUtcEnabled; - - public KnowledgeableMessageFormat(boolean elementIdEnabled) { - this.elementIdEnabled = elementIdEnabled; - } - - @Override - public Writer newWriter(PackOutput output, ValueFactory valueFactory) { - return new KnowledgeableMessageWriter( - output, elementIdEnabled, dateTimeUtcEnabled, (TestValueFactory) valueFactory); - } - - @Override - public void enableDateTimeUtc() { - dateTimeUtcEnabled = true; - } - - private static class KnowledgeableMessageWriter extends AbstractMessageWriter { - KnowledgeableMessageWriter( - PackOutput output, boolean enableElementId, boolean dateTimeUtcEnabled, TestValueFactory valueFactory) { - super( - new KnowledgeableValuePacker(output, enableElementId, dateTimeUtcEnabled), - buildEncoders(), - valueFactory); - } - - static Map buildEncoders() { - Map result = new HashMap<>(10); - // request message encoders - result.put(DiscardAllMessage.SIGNATURE, new DiscardAllMessageEncoder()); - result.put(PullAllMessage.SIGNATURE, new PullAllMessageEncoder()); - result.put(ResetMessage.SIGNATURE, new ResetMessageEncoder()); - // response message encoders - result.put(FailureMessage.SIGNATURE, new FailureMessageEncoder()); - result.put(IgnoredMessage.SIGNATURE, new IgnoredMessageEncoder()); - result.put(RecordMessage.SIGNATURE, new RecordMessageEncoder()); - result.put(SuccessMessage.SIGNATURE, new SuccessMessageEncoder()); - return result; - } - } - - private static class KnowledgeableValuePacker extends CommonValuePacker { - private final boolean elementIdEnabled; - - KnowledgeableValuePacker(PackOutput output, boolean elementIdEnabled, boolean dateTimeUtcEnabled) { - super(output, dateTimeUtcEnabled); - this.elementIdEnabled = elementIdEnabled; - } - - @Override - protected void packInternalValue(Value value) throws IOException { - switch (value.type()) { - case NODE -> { - var node = ((TestValue) value).asNode(); - packNode(node); - } - case RELATIONSHIP -> { - var rel = ((TestValue) value).asRelationship(); - packRelationship(rel); - } - case PATH -> { - var path = ((TestValue) value).asPath(); - packPath(path); - } - default -> super.packInternalValue(value); - } - } - - private void packPath(TestPath path) throws IOException { - packer.packStructHeader(3, CommonValueUnpacker.PATH); - - // Unique nodes - Map nodeIdx = new LinkedHashMap<>(path.length() + 1); - for (var node : path.nodes()) { - if (!nodeIdx.containsKey(node)) { - nodeIdx.put(node, nodeIdx.size()); - } - } - packer.packListHeader(nodeIdx.size()); - for (var node : nodeIdx.keySet()) { - packNode(node); - } - - // Unique rels - Map relIdx = new LinkedHashMap<>(path.length()); - for (var rel : path.relationships()) { - if (!relIdx.containsKey(rel)) { - relIdx.put(rel, relIdx.size() + 1); - } - } - packer.packListHeader(relIdx.size()); - for (var rel : relIdx.keySet()) { - packer.packStructHeader(elementIdEnabled ? 4 : 3, CommonValueUnpacker.UNBOUND_RELATIONSHIP); - packer.pack(rel.id()); - packer.pack(rel.typeString()); - packProperties(rel); - if (elementIdEnabled) { - packer.pack(rel.elementId()); - } - } - - // Sequence - packer.packListHeader(path.length() * 2); - for (var seg : path) { - var rel = seg.relationship(); - var relEndId = rel.endNodeId(); - var segEndId = seg.end().id(); - var size = relEndId == segEndId ? relIdx.get(rel) : -relIdx.get(rel); - packer.pack(size); - packer.pack(nodeIdx.get(seg.end())); - } - } - - private void packRelationship(TestRelationship rel) throws IOException { - packer.packStructHeader(elementIdEnabled ? 8 : 5, CommonValueUnpacker.RELATIONSHIP); - packer.pack(rel.id()); - packer.pack(rel.startNodeId()); - packer.pack(rel.endNodeId()); - - packer.pack(rel.typeString()); - - packProperties(rel); - - if (elementIdEnabled) { - packer.pack(rel.elementId()); - packer.pack(rel.startNodeElementId()); - packer.pack(rel.endNodeElementId()); - } - } - - private void packNode(TestNode node) throws IOException { - packer.packStructHeader(elementIdEnabled ? 4 : 3, CommonValueUnpacker.NODE); - packer.pack(node.id()); - - var labels = node.labels(); - packer.packListHeader( - (int) StreamSupport.stream(labels.spliterator(), false).count()); - for (var label : labels) { - packer.pack(label); - } - - packProperties(node); - - if (elementIdEnabled) { - packer.pack(node.elementId()); - } - } - - private void packProperties(Entity entity) throws IOException { - var keys = entity.keys(); - packer.packMapHeader(entity.size()); - for (var propKey : keys) { - packer.pack(propKey); - packInternalValue(entity.get(propKey)); - } - } - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/MemorizingInboundMessageDispatcher.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/MemorizingInboundMessageDispatcher.java deleted file mode 100644 index bb15073dc1..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/MemorizingInboundMessageDispatcher.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging; - -import io.netty.channel.Channel; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CopyOnWriteArrayList; -import org.neo4j.driver.internal.bolt.api.GqlError; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.basicimpl.impl.async.inbound.InboundMessageDispatcher; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.FailureMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.IgnoredMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.RecordMessage; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.SuccessMessage; - -public class MemorizingInboundMessageDispatcher extends InboundMessageDispatcher { - private final List messages = new CopyOnWriteArrayList<>(); - - public MemorizingInboundMessageDispatcher(Channel channel, LoggingProvider logging) { - super(channel, logging); - } - - public List messages() { - return new ArrayList<>(messages); - } - - @Override - public void handleSuccessMessage(Map meta) { - messages.add(new SuccessMessage(meta)); - } - - @Override - public void handleRecordMessage(Value[] fields) { - messages.add(new RecordMessage(fields)); - } - - @Override - public void handleFailureMessage(GqlError gqlError) { - messages.add(new FailureMessage(gqlError.code(), gqlError.message())); - } - - @Override - public void handleIgnoredMessage() { - messages.add(IgnoredMessage.IGNORED); - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/RecordMessageEncoder.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/RecordMessageEncoder.java deleted file mode 100644 index e6d3bed2aa..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/RecordMessageEncoder.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging; - -import java.io.IOException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.RecordMessage; - -public class RecordMessageEncoder implements MessageEncoder { - @Override - public void encode(Message message, ValuePacker packer, ValueFactory valueFactory) throws IOException { - var recordMessage = (RecordMessage) message; - var fields = recordMessage.fields(); - packer.packStructHeader(1, recordMessage.signature()); - packer.pack(valueFactory.value(fields)); // pack list of fields - } -} diff --git a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/SuccessMessageEncoder.java b/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/SuccessMessageEncoder.java deleted file mode 100644 index 7ab591946e..0000000000 --- a/bolt-api-netty/src/test/java/org/neo4j/driver/internal/bolt/basicimpl/impl/util/messaging/SuccessMessageEncoder.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging; - -import java.io.IOException; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.Message; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.MessageEncoder; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.ValuePacker; -import org.neo4j.driver.internal.bolt.basicimpl.impl.messaging.response.SuccessMessage; - -public class SuccessMessageEncoder implements MessageEncoder { - @Override - public void encode(Message message, ValuePacker packer, ValueFactory valueFactory) throws IOException { - var successMessage = (SuccessMessage) message; - packer.packStructHeader(1, successMessage.signature()); - packer.pack(successMessage.metadata()); - } -} diff --git a/bolt-api-pooled/LICENSES.txt b/bolt-api-pooled/LICENSES.txt deleted file mode 100644 index f8e0fd3292..0000000000 --- a/bolt-api-pooled/LICENSES.txt +++ /dev/null @@ -1,5 +0,0 @@ -This file contains the full license text of the included third party -libraries. For an overview of the licenses see the NOTICE.txt file. - - - diff --git a/bolt-api-pooled/NOTICE.txt b/bolt-api-pooled/NOTICE.txt deleted file mode 100644 index c3bf48c6fc..0000000000 --- a/bolt-api-pooled/NOTICE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) "Neo4j" -Neo4j Sweden AB [https://neo4j.com] - -This file is part of Neo4j. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -Full license texts are found in LICENSES.txt. - - -Third-party licenses --------------------- - diff --git a/bolt-api-pooled/pom.xml b/bolt-api-pooled/pom.xml deleted file mode 100644 index b65566e387..0000000000 --- a/bolt-api-pooled/pom.xml +++ /dev/null @@ -1,70 +0,0 @@ - - 4.0.0 - - - org.neo4j.driver - neo4j-java-driver-parent - 5.28-SNAPSHOT - - - neo4j-bolt-api-pooled - - jar - Neo4j Bolt API Pooled - https://github.com/neo4j/neo4j-java-driver - - - ${project.basedir}/.. - ,-try - - - - - org.neo4j.driver - neo4j-bolt-api - ${project.version} - - - - org.mockito - mockito-core - - - org.junit.jupiter - junit-jupiter - - - - - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-javadoc-plugin - - - org.apache.maven.plugins - maven-failsafe-plugin - - - org.apache.maven.surefire - surefire-junit-platform - ${surefire.and.failsafe.version} - - - - - - - - scm:git:git://github.com/neo4j/neo4j-java-driver.git - scm:git:git@github.com:neo4j/neo4j-java-driver.git - https://github.com/neo4j/neo4j-java-driver - - - diff --git a/bolt-api-pooled/src/main/java/module-info.java b/bolt-api-pooled/src/main/java/module-info.java deleted file mode 100644 index 0d9eae47d2..0000000000 --- a/bolt-api-pooled/src/main/java/module-info.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * The Neo4j Bolt API pooled implementation module. - */ -module org.neo4j.bolt.pooled { - exports org.neo4j.driver.internal.bolt.pooledimpl; - - requires transitive org.neo4j.bolt.api; -} diff --git a/bolt-api-pooled/src/main/java/org/neo4j/driver/internal/bolt/pooledimpl/PooledBoltConnectionProvider.java b/bolt-api-pooled/src/main/java/org/neo4j/driver/internal/bolt/pooledimpl/PooledBoltConnectionProvider.java deleted file mode 100644 index c684b777cc..0000000000 --- a/bolt-api-pooled/src/main/java/org/neo4j/driver/internal/bolt/pooledimpl/PooledBoltConnectionProvider.java +++ /dev/null @@ -1,698 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.pooledimpl; - -import java.time.Clock; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Queue; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.AuthToken; -import org.neo4j.driver.internal.bolt.api.BasicResponseHandler; -import org.neo4j.driver.internal.bolt.api.BoltAgent; -import org.neo4j.driver.internal.bolt.api.BoltConnection; -import org.neo4j.driver.internal.bolt.api.BoltConnectionProvider; -import org.neo4j.driver.internal.bolt.api.BoltConnectionState; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.MetricsListener; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; -import org.neo4j.driver.internal.bolt.api.exception.BoltTransientException; -import org.neo4j.driver.internal.bolt.api.exception.MinVersionAcquisitionException; -import org.neo4j.driver.internal.bolt.pooledimpl.impl.PooledBoltConnection; -import org.neo4j.driver.internal.bolt.pooledimpl.impl.util.FutureUtil; - -public class PooledBoltConnectionProvider implements BoltConnectionProvider { - private final System.Logger log; - private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); - private final BoltConnectionProvider boltConnectionProvider; - private final List pooledConnectionEntries; - private final Queue> pendingAcquisitions; - private final int maxSize; - private final long acquisitionTimeout; - private final long maxLifetime; - private final long idleBeforeTest; - private final Clock clock; - private final MetricsListener metricsListener; - private final BoltServerAddress address; - private final RoutingContext routingContext; - private final BoltAgent boltAgent; - private final String userAgent; - private final int connectTimeoutMillis; - private final String poolId; - - private CompletionStage closeStage; - private long minAuthTimestamp; - - public PooledBoltConnectionProvider( - BoltConnectionProvider boltConnectionProvider, - int maxSize, - long acquisitionTimeout, - long maxLifetime, - long idleBeforeTest, - Clock clock, - LoggingProvider logging, - MetricsListener metricsListener, - BoltServerAddress address, - RoutingContext routingContext, - BoltAgent boltAgent, - String userAgent, - int connectTimeoutMillis) { - this.boltConnectionProvider = boltConnectionProvider; - this.pooledConnectionEntries = new ArrayList<>(); - this.pendingAcquisitions = new ArrayDeque<>(100); - this.maxSize = maxSize; - this.acquisitionTimeout = acquisitionTimeout; - this.maxLifetime = maxLifetime; - this.idleBeforeTest = idleBeforeTest; - this.clock = Objects.requireNonNull(clock); - this.log = logging.getLog(getClass()); - this.metricsListener = Objects.requireNonNull(metricsListener); - this.address = Objects.requireNonNull(address); - this.routingContext = Objects.requireNonNull(routingContext); - this.boltAgent = Objects.requireNonNull(boltAgent); - this.userAgent = Objects.requireNonNull(userAgent); - this.connectTimeoutMillis = connectTimeoutMillis; - this.poolId = poolId(address); - metricsListener.registerPoolMetrics( - poolId, - address, - () -> { - synchronized (this) { - return (int) pooledConnectionEntries.stream() - .filter(entry -> !entry.available) - .count(); - } - }, - () -> { - synchronized (this) { - return (int) pooledConnectionEntries.stream() - .filter(entry -> entry.available) - .count(); - } - }); - } - - @SuppressWarnings({"ReassignedVariable"}) - @Override - public CompletionStage connect( - BoltServerAddress ignoredAddress, - RoutingContext ignoredRoutingContext, - BoltAgent ignoredBoltAgent, - String ignoredUserAgent, - int ignoredConnectTimeoutMillis, - SecurityPlan securityPlan, - DatabaseName databaseName, - Supplier> authTokenStageSupplier, - AccessMode mode, - Set bookmarks, - String impersonatedUser, - BoltProtocolVersion minVersion, - NotificationConfig notificationConfig, - Consumer databaseNameConsumer, - Map additionalParameters) { - synchronized (this) { - if (closeStage != null) { - return CompletableFuture.failedFuture(new IllegalStateException("Connection provider is closed.")); - } - } - - var acquisitionFuture = new CompletableFuture(); - - authTokenStageSupplier.get().whenComplete((authToken, authThrowable) -> { - if (authThrowable != null) { - acquisitionFuture.completeExceptionally(authThrowable); - return; - } - - var beforeAcquiringOrCreatingEvent = metricsListener.createListenerEvent(); - metricsListener.beforeAcquiringOrCreating(poolId, beforeAcquiringOrCreatingEvent); - acquisitionFuture.whenComplete((connection, throwable) -> { - throwable = FutureUtil.completionExceptionCause(throwable); - if (throwable != null) { - if (throwable instanceof TimeoutException) { - metricsListener.afterTimedOutToAcquireOrCreate(poolId); - } - } else { - metricsListener.afterAcquiredOrCreated(poolId, beforeAcquiringOrCreatingEvent); - } - metricsListener.afterAcquiringOrCreating(poolId); - }); - connect( - acquisitionFuture, - securityPlan, - databaseName, - authToken, - authTokenStageSupplier, - mode, - bookmarks, - impersonatedUser, - minVersion, - notificationConfig); - }); - - return acquisitionFuture - .whenComplete((ignored, throwable) -> { - if (throwable == null) { - databaseNameConsumer.accept(databaseName); - } - }) - .thenApply(Function.identity()); - } - - @SuppressWarnings({"DuplicatedCode", "ConstantValue"}) - private void connect( - CompletableFuture acquisitionFuture, - SecurityPlan securityPlan, - DatabaseName databaseName, - AuthToken authToken, - Supplier> authTokenStageSupplier, - AccessMode mode, - Set bookmarks, - String impersonatedUser, - BoltProtocolVersion minVersion, - NotificationConfig notificationConfig) { - - ConnectionEntryWithMetadata connectionEntryWithMetadata = null; - Throwable pendingAcquisitionsFull = null; - var empty = new AtomicBoolean(); - synchronized (this) { - try { - empty.set(pooledConnectionEntries.isEmpty()); - try { - // go over existing entries first - connectionEntryWithMetadata = acquireExistingEntry(authToken, minVersion); - } catch (MinVersionAcquisitionException e) { - acquisitionFuture.completeExceptionally(e); - return; - } - - if (connectionEntryWithMetadata == null) { - // no entry found - if (pooledConnectionEntries.size() < maxSize) { - // space is available, reserve - var acquiredEntry = new ConnectionEntry(); - pooledConnectionEntries.add(acquiredEntry); - connectionEntryWithMetadata = new ConnectionEntryWithMetadata(acquiredEntry, false); - } else { - // fallback to queue - if (pendingAcquisitions.size() < 100 && !acquisitionFuture.isDone()) { - if (acquisitionTimeout > 0) { - pendingAcquisitions.add(acquisitionFuture); - } - // schedule timeout - executorService.schedule( - () -> { - synchronized (this) { - pendingAcquisitions.remove(acquisitionFuture); - } - try { - acquisitionFuture.completeExceptionally(new TimeoutException( - "Unable to acquire connection from the pool within configured maximum time of " - + acquisitionTimeout + "ms")); - } catch (Throwable throwable) { - log.log( - System.Logger.Level.WARNING, - "Unexpected error occurred.", - throwable); - } - }, - acquisitionTimeout, - TimeUnit.MILLISECONDS); - } else { - pendingAcquisitionsFull = - new BoltTransientException("Connection pool pending acquisition queue is full."); - } - } - } - - } catch (Throwable throwable) { - if (connectionEntryWithMetadata != null) { - if (connectionEntryWithMetadata.connectionEntry.connection != null) { - // not new entry, make it available - connectionEntryWithMetadata.connectionEntry.available = true; - } else { - // new empty entry - pooledConnectionEntries.remove(connectionEntryWithMetadata.connectionEntry); - } - } - pendingAcquisitions.remove(acquisitionFuture); - acquisitionFuture.completeExceptionally(throwable); - } - } - - if (pendingAcquisitionsFull != null) { - // no space in queue was available - acquisitionFuture.completeExceptionally(pendingAcquisitionsFull); - } else if (connectionEntryWithMetadata != null) { - if (connectionEntryWithMetadata.connectionEntry.connection != null) { - // entry with connection - var entryWithMetadata = connectionEntryWithMetadata; - var entry = entryWithMetadata.connectionEntry; - - livenessCheckStage(entry).whenComplete((ignored, throwable) -> { - if (throwable != null) { - // liveness check failed - purge(entry); - connect( - acquisitionFuture, - securityPlan, - databaseName, - authToken, - authTokenStageSupplier, - mode, - bookmarks, - impersonatedUser, - minVersion, - notificationConfig); - } else { - // liveness check green or not needed - var inUseEvent = metricsListener.createListenerEvent(); - var pooledConnection = new PooledBoltConnection( - entry.connection, - this, - () -> { - release(entry); - metricsListener.afterConnectionReleased(poolId, inUseEvent); - }, - () -> { - purge(entry); - metricsListener.afterConnectionReleased(poolId, inUseEvent); - }); - reauthStage(entryWithMetadata, authToken).whenComplete((ignored2, throwable2) -> { - if (!acquisitionFuture.complete(pooledConnection)) { - // acquisition timed out - CompletableFuture pendingAcquisition; - synchronized (this) { - pendingAcquisition = pendingAcquisitions.poll(); - if (pendingAcquisition == null) { - // nothing pending, just make the entry available - entry.available = true; - } - } - if (pendingAcquisition != null) { - if (pendingAcquisition.complete(pooledConnection)) { - metricsListener.afterConnectionCreated(poolId, inUseEvent); - } - } - } else { - metricsListener.afterConnectionCreated(poolId, inUseEvent); - } - }); - } - }); - } else { - // get reserved entry - var createEvent = metricsListener.createListenerEvent(); - metricsListener.beforeCreating(poolId, createEvent); - var entry = connectionEntryWithMetadata.connectionEntry; - boltConnectionProvider - .connect( - address, - routingContext, - boltAgent, - userAgent, - connectTimeoutMillis, - securityPlan, - databaseName, - empty.get() - ? () -> CompletableFuture.completedStage(authToken) - : authTokenStageSupplier, - mode, - bookmarks, - impersonatedUser, - minVersion, - notificationConfig, - (ignored) -> {}, - Collections.emptyMap()) - .whenComplete((boltConnection, throwable) -> { - var error = FutureUtil.completionExceptionCause(throwable); - if (error != null) { - synchronized (this) { - pooledConnectionEntries.remove(entry); - } - metricsListener.afterFailedToCreate(poolId); - acquisitionFuture.completeExceptionally(error); - } else { - synchronized (this) { - entry.connection = boltConnection; - entry.createdTimestamp = clock.millis(); - } - metricsListener.afterCreated(poolId, createEvent); - var inUseEvent = metricsListener.createListenerEvent(); - var pooledConnection = new PooledBoltConnection( - boltConnection, - this, - () -> { - release(entry); - metricsListener.afterConnectionReleased(poolId, inUseEvent); - }, - () -> { - purge(entry); - metricsListener.afterConnectionReleased(poolId, inUseEvent); - }); - if (!acquisitionFuture.complete(pooledConnection)) { - // acquisition timed out - CompletableFuture pendingAcquisition; - synchronized (this) { - pendingAcquisition = pendingAcquisitions.poll(); - if (pendingAcquisition == null) { - // nothing pending, just make the entry available - entry.available = true; - } - } - if (pendingAcquisition != null) { - if (pendingAcquisition.complete(pooledConnection)) { - metricsListener.afterConnectionCreated(poolId, inUseEvent); - } - } - } else { - metricsListener.afterConnectionCreated(poolId, inUseEvent); - } - } - }); - } - } - } - - private synchronized ConnectionEntryWithMetadata acquireExistingEntry( - AuthToken authToken, BoltProtocolVersion minVersion) { - ConnectionEntryWithMetadata connectionEntryWithMetadata = null; - var iterator = pooledConnectionEntries.iterator(); - while (iterator.hasNext()) { - var connectionEntry = iterator.next(); - - // unavailable - if (!connectionEntry.available) { - continue; - } - - var connection = connectionEntry.connection; - // unusable - if (connection.state() != BoltConnectionState.OPEN) { - connection.close(); - iterator.remove(); - continue; - } - - // lower version is present - if (minVersion != null && minVersion.compareTo(connection.protocolVersion()) > 0) { - throw new MinVersionAcquisitionException("lower version", connection.protocolVersion()); - } - - // exceeded max lifetime - if (maxLifetime > 0) { - var currentTime = clock.millis(); - if (currentTime - connectionEntry.createdTimestamp > maxLifetime) { - connection.close(); - iterator.remove(); - metricsListener.afterClosed(poolId); - continue; - } - } - - // the pool must not have unauthenticated connections - var authInfo = connection.authInfo().toCompletableFuture().getNow(null); - - var expiredByError = minAuthTimestamp > 0 && authInfo.authAckMillis() <= minAuthTimestamp; - var authMatches = authToken.equals(authInfo.authToken()); - var reauthNeeded = expiredByError || !authMatches; - - if (reauthNeeded) { - if (new BoltProtocolVersion(5, 1).compareTo(connectionEntry.connection.protocolVersion()) > 0) { - log.log(System.Logger.Level.DEBUG, "reauth is not supported, the connection is voided"); - iterator.remove(); - connectionEntry.connection.close().whenComplete((ignored, throwable) -> { - if (throwable != null) { - log.log( - System.Logger.Level.WARNING, - "Connection close has failed with %s.", - throwable.getClass().getCanonicalName()); - } - }); - continue; - } - } - log.log(System.Logger.Level.DEBUG, "Connection acquired from the pool. " + address); - connectionEntry.available = false; - connectionEntryWithMetadata = new ConnectionEntryWithMetadata(connectionEntry, reauthNeeded); - break; - } - return connectionEntryWithMetadata; - } - - private CompletionStage reauthStage( - ConnectionEntryWithMetadata connectionEntryWithMetadata, AuthToken authToken) { - CompletionStage stage; - if (connectionEntryWithMetadata.reauthNeeded) { - stage = connectionEntryWithMetadata - .connectionEntry - .connection - .logoff() - .thenCompose(conn -> conn.logon(authToken)) - .handle((ignored, throwable) -> { - if (throwable != null) { - connectionEntryWithMetadata.connectionEntry.connection.close(); - synchronized (this) { - pooledConnectionEntries.remove(connectionEntryWithMetadata.connectionEntry); - } - } - return null; - }); - } else { - stage = CompletableFuture.completedStage(null); - } - return stage; - } - - private CompletionStage livenessCheckStage(ConnectionEntry entry) { - CompletionStage stage; - if (idleBeforeTest >= 0 && entry.lastUsedTimestamp + idleBeforeTest < clock.millis()) { - var resetHandler = new BasicResponseHandler(); - stage = entry.connection - .reset() - .thenCompose(conn -> conn.flush(resetHandler)) - .thenCompose(ignored -> resetHandler.summaries()) - .thenApply(ignored -> null); - } else { - stage = CompletableFuture.completedStage(null); - } - return stage; - } - - @Override - public CompletionStage verifyConnectivity( - BoltServerAddress ignoredAddress, - RoutingContext ignoredRoutingContext, - BoltAgent ignoredBoltAgent, - String ignoredUserAgent, - int ignoredConnectTimeoutMillis, - SecurityPlan securityPlan, - AuthToken authToken) { - return connect( - address, - routingContext, - boltAgent, - userAgent, - connectTimeoutMillis, - securityPlan, - null, - () -> CompletableFuture.completedStage(authToken), - AccessMode.WRITE, - Collections.emptySet(), - null, - null, - null, - (ignored) -> {}, - Collections.emptyMap()) - .thenCompose(BoltConnection::close); - } - - @Override - public CompletionStage supportsMultiDb( - BoltServerAddress ignoredAddress, - RoutingContext ignoredRoutingContext, - BoltAgent ignoredBoltAgent, - String ignoredUserAgent, - int ignoredConnectTimeoutMillis, - SecurityPlan securityPlan, - AuthToken authToken) { - return connect( - address, - routingContext, - boltAgent, - userAgent, - connectTimeoutMillis, - securityPlan, - null, - () -> CompletableFuture.completedStage(authToken), - AccessMode.WRITE, - Collections.emptySet(), - null, - null, - null, - (ignored) -> {}, - Collections.emptyMap()) - .thenCompose(boltConnection -> { - var supports = boltConnection.protocolVersion().compareTo(new BoltProtocolVersion(4, 0)) >= 0; - return boltConnection.close().thenApply(ignored -> supports); - }); - } - - @Override - public CompletionStage supportsSessionAuth( - BoltServerAddress ignoredAddress, - RoutingContext ignoredRoutingContext, - BoltAgent ignoredBoltAgent, - String ignoredUserAgent, - int ignoredConnectTimeoutMillis, - SecurityPlan securityPlan, - AuthToken authToken) { - return connect( - address, - routingContext, - boltAgent, - userAgent, - connectTimeoutMillis, - securityPlan, - null, - () -> CompletableFuture.completedStage(authToken), - AccessMode.WRITE, - Collections.emptySet(), - null, - null, - null, - (ignored) -> {}, - Collections.emptyMap()) - .thenCompose(boltConnection -> { - var supports = new BoltProtocolVersion(5, 1).compareTo(boltConnection.protocolVersion()) <= 0; - return boltConnection.close().thenApply(ignored -> supports); - }); - } - - @Override - public CompletionStage close() { - CompletionStage closeStage; - synchronized (this) { - if (this.closeStage == null) { - this.closeStage = CompletableFuture.completedStage(null); - var iterator = pooledConnectionEntries.iterator(); - while (iterator.hasNext()) { - var entry = iterator.next(); - if (entry.connection != null && entry.connection.state() == BoltConnectionState.OPEN) { - this.closeStage = this.closeStage.thenCompose( - ignored -> entry.connection.close().exceptionally(throwable -> null)); - } - iterator.remove(); - } - metricsListener.removePoolMetrics(poolId); - this.closeStage = this.closeStage - .thenCompose(ignored -> boltConnectionProvider.close()) - .exceptionally(throwable -> null) - .whenComplete((ignored, throwable) -> executorService.shutdown()); - } - closeStage = this.closeStage; - } - return closeStage; - } - - synchronized int size() { - return pooledConnectionEntries.size(); - } - - synchronized int inUse() { - return pooledConnectionEntries.stream() - .filter(entry -> !entry.available) - .toList() - .size(); - } - - private String poolId(BoltServerAddress serverAddress) { - return String.format("%s:%d-%d", serverAddress.host(), serverAddress.port(), this.hashCode()); - } - - private void release(ConnectionEntry entry) { - CompletableFuture pendingAcquisition; - synchronized (this) { - entry.lastUsedTimestamp = clock.millis(); - pendingAcquisition = pendingAcquisitions.poll(); - if (pendingAcquisition == null) { - // nothing pending, just make the entry available - entry.available = true; - } - } - if (pendingAcquisition != null) { - var inUseEvent = metricsListener.createListenerEvent(); - if (pendingAcquisition.complete(new PooledBoltConnection( - entry.connection, - this, - () -> { - release(entry); - metricsListener.afterConnectionReleased(poolId, inUseEvent); - }, - () -> { - purge(entry); - metricsListener.afterConnectionReleased(poolId, inUseEvent); - }))) { - metricsListener.afterConnectionCreated(poolId, inUseEvent); - } - } - log.log(System.Logger.Level.DEBUG, "Connection released to the pool."); - } - - private void purge(ConnectionEntry entry) { - synchronized (this) { - pooledConnectionEntries.remove(entry); - } - metricsListener.afterClosed(poolId); - entry.connection.close(); - log.log(System.Logger.Level.DEBUG, "Connection purged from the pool."); - } - - public synchronized void onExpired() { - var now = clock.millis(); - minAuthTimestamp = Math.max(minAuthTimestamp, now); - } - - private static class ConnectionEntry { - private BoltConnection connection; - private boolean available; - private long createdTimestamp; - private long lastUsedTimestamp; - } - - private record ConnectionEntryWithMetadata(ConnectionEntry connectionEntry, boolean reauthNeeded) {} -} diff --git a/bolt-api-pooled/src/main/java/org/neo4j/driver/internal/bolt/pooledimpl/impl/PooledBoltConnection.java b/bolt-api-pooled/src/main/java/org/neo4j/driver/internal/bolt/pooledimpl/impl/PooledBoltConnection.java deleted file mode 100644 index b717136b65..0000000000 --- a/bolt-api-pooled/src/main/java/org/neo4j/driver/internal/bolt/pooledimpl/impl/PooledBoltConnection.java +++ /dev/null @@ -1,369 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.pooledimpl.impl; - -import java.time.Duration; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.AuthInfo; -import org.neo4j.driver.internal.bolt.api.AuthToken; -import org.neo4j.driver.internal.bolt.api.BasicResponseHandler; -import org.neo4j.driver.internal.bolt.api.BoltConnection; -import org.neo4j.driver.internal.bolt.api.BoltConnectionState; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.ResponseHandler; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; -import org.neo4j.driver.internal.bolt.api.TransactionType; -import org.neo4j.driver.internal.bolt.api.exception.BoltFailureException; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.CommitSummary; -import org.neo4j.driver.internal.bolt.api.summary.DiscardSummary; -import org.neo4j.driver.internal.bolt.api.summary.LogoffSummary; -import org.neo4j.driver.internal.bolt.api.summary.LogonSummary; -import org.neo4j.driver.internal.bolt.api.summary.PullSummary; -import org.neo4j.driver.internal.bolt.api.summary.ResetSummary; -import org.neo4j.driver.internal.bolt.api.summary.RollbackSummary; -import org.neo4j.driver.internal.bolt.api.summary.RouteSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.summary.TelemetrySummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.pooledimpl.PooledBoltConnectionProvider; - -public class PooledBoltConnection implements BoltConnection { - private final BoltConnection delegate; - private final PooledBoltConnectionProvider provider; - private final Runnable releaseRunnable; - private final Runnable purgeRunnable; - private CompletableFuture closeFuture; - - public PooledBoltConnection( - BoltConnection delegate, - PooledBoltConnectionProvider provider, - Runnable releaseRunnable, - Runnable purgeRunnable) { - this.delegate = Objects.requireNonNull(delegate); - this.provider = Objects.requireNonNull(provider); - this.releaseRunnable = Objects.requireNonNull(releaseRunnable); - this.purgeRunnable = Objects.requireNonNull(purgeRunnable); - } - - @Override - public CompletionStage onLoop() { - return delegate.onLoop(); - } - - @Override - public CompletionStage route( - DatabaseName databaseName, String impersonatedUser, Set bookmarks) { - return delegate.route(databaseName, impersonatedUser, bookmarks).thenApply(ignored -> this); - } - - @Override - public CompletionStage beginTransaction( - DatabaseName databaseName, - AccessMode accessMode, - String impersonatedUser, - Set bookmarks, - TransactionType transactionType, - Duration txTimeout, - Map txMetadata, - String txType, - NotificationConfig notificationConfig) { - return delegate.beginTransaction( - databaseName, - accessMode, - impersonatedUser, - bookmarks, - transactionType, - txTimeout, - txMetadata, - txType, - notificationConfig) - .thenApply(ignored -> this); - } - - @Override - public CompletionStage runInAutoCommitTransaction( - DatabaseName databaseName, - AccessMode accessMode, - String impersonatedUser, - Set bookmarks, - String query, - Map parameters, - Duration txTimeout, - Map txMetadata, - NotificationConfig notificationConfig) { - return delegate.runInAutoCommitTransaction( - databaseName, - accessMode, - impersonatedUser, - bookmarks, - query, - parameters, - txTimeout, - txMetadata, - notificationConfig) - .thenApply(ignored -> this); - } - - @Override - public CompletionStage run(String query, Map parameters) { - return delegate.run(query, parameters).thenApply(ignored -> this); - } - - @Override - public CompletionStage pull(long qid, long request) { - return delegate.pull(qid, request).thenApply(ignored -> this); - } - - @Override - public CompletionStage discard(long qid, long number) { - return delegate.discard(qid, number).thenApply(ignored -> this); - } - - @Override - public CompletionStage commit() { - return delegate.commit().thenApply(ignored -> this); - } - - @Override - public CompletionStage rollback() { - return delegate.rollback().thenApply(ignored -> this); - } - - @Override - public CompletionStage reset() { - return delegate.reset().thenApply(ignored -> this); - } - - @Override - public CompletionStage logoff() { - return delegate.logoff().thenApply(ignored -> this); - } - - @Override - public CompletionStage logon(AuthToken authToken) { - return delegate.logon(authToken).thenApply(ignored -> this); - } - - @Override - public CompletionStage telemetry(TelemetryApi telemetryApi) { - return delegate.telemetry(telemetryApi).thenApply(ignored -> this); - } - - @Override - public CompletionStage clear() { - return delegate.clear(); - } - - @Override - public CompletionStage flush(ResponseHandler handler) { - return delegate.flush(new ResponseHandler() { - - @Override - public void onError(Throwable throwable) { - if (throwable instanceof BoltFailureException boltFailureException) { - if ("Neo.ClientError.Security.AuthorizationExpired".equals(boltFailureException.code())) { - provider.onExpired(); - } - } - handler.onError(throwable); - } - - @Override - public void onBeginSummary(BeginSummary summary) { - handler.onBeginSummary(summary); - } - - @Override - public void onRunSummary(RunSummary summary) { - handler.onRunSummary(summary); - } - - @Override - public void onRecord(Value[] fields) { - handler.onRecord(fields); - } - - @Override - public void onPullSummary(PullSummary summary) { - handler.onPullSummary(summary); - } - - @Override - public void onDiscardSummary(DiscardSummary summary) { - handler.onDiscardSummary(summary); - } - - @Override - public void onCommitSummary(CommitSummary summary) { - handler.onCommitSummary(summary); - } - - @Override - public void onRollbackSummary(RollbackSummary summary) { - handler.onRollbackSummary(summary); - } - - @Override - public void onResetSummary(ResetSummary summary) { - handler.onResetSummary(summary); - } - - @Override - public void onRouteSummary(RouteSummary summary) { - handler.onRouteSummary(summary); - } - - @Override - public void onLogoffSummary(LogoffSummary summary) { - handler.onLogoffSummary(summary); - } - - @Override - public void onLogonSummary(LogonSummary summary) { - handler.onLogonSummary(summary); - } - - @Override - public void onTelemetrySummary(TelemetrySummary summary) { - handler.onTelemetrySummary(summary); - } - - @Override - public void onIgnored() { - handler.onIgnored(); - } - - @Override - public void onComplete() { - handler.onComplete(); - } - }) - .whenComplete((ignored, throwable) -> { - if (throwable != null) { - if (delegate.state() == BoltConnectionState.CLOSED) { - purgeRunnable.run(); - } - } - }); - } - - @Override - public CompletionStage forceClose(String reason) { - return delegate.forceClose(reason).whenComplete((closeResult, closeThrowable) -> purgeRunnable.run()); - } - - @Override - public CompletionStage close() { - CompletableFuture closeFuture; - var close = false; - synchronized (this) { - if (this.closeFuture == null) { - this.closeFuture = new CompletableFuture<>(); - close = true; - } - closeFuture = this.closeFuture; - } - - if (close) { - if (delegate.state() == BoltConnectionState.CLOSED) { - purgeRunnable.run(); - closeFuture.complete(null); - return closeFuture; - } else if (delegate.state() == BoltConnectionState.ERROR) { - purgeRunnable.run(); - closeFuture.complete(null); - return closeFuture; - } - - var resetHandler = new BasicResponseHandler(); - delegate.reset() - .thenCompose(boltConnection -> boltConnection.flush(resetHandler)) - .thenCompose(ignored -> resetHandler.summaries()) - .whenComplete((ignored, throwable) -> { - if (throwable != null) { - delegate.close().whenComplete((closeResult, closeThrowable) -> purgeRunnable.run()); - } else { - CompletableFuture.completedStage(null) - .whenComplete((ignoredResult, nothing) -> releaseRunnable.run()); - } - closeFuture.complete(null); - }); - } - - return closeFuture; - } - - @Override - public CompletionStage setReadTimeout(Duration duration) { - return delegate.setReadTimeout(duration); - } - - @Override - public BoltConnectionState state() { - return delegate.state(); - } - - @Override - public CompletionStage authInfo() { - return delegate.authInfo(); - } - - @Override - public String serverAgent() { - return delegate.serverAgent(); - } - - @Override - public BoltServerAddress serverAddress() { - return delegate.serverAddress(); - } - - @Override - public BoltProtocolVersion protocolVersion() { - return delegate.protocolVersion(); - } - - @Override - public boolean telemetrySupported() { - return delegate.telemetrySupported(); - } - - @Override - public boolean serverSideRoutingEnabled() { - return delegate.serverSideRoutingEnabled(); - } - - @Override - public Optional defaultReadTimeout() { - return delegate.defaultReadTimeout(); - } - - // internal use only - public BoltConnection delegate() { - return delegate; - } -} diff --git a/bolt-api-pooled/src/main/java/org/neo4j/driver/internal/bolt/pooledimpl/impl/util/FutureUtil.java b/bolt-api-pooled/src/main/java/org/neo4j/driver/internal/bolt/pooledimpl/impl/util/FutureUtil.java deleted file mode 100644 index 408a61387e..0000000000 --- a/bolt-api-pooled/src/main/java/org/neo4j/driver/internal/bolt/pooledimpl/impl/util/FutureUtil.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.pooledimpl.impl.util; - -import java.util.concurrent.CompletionException; - -public class FutureUtil { - public static Throwable completionExceptionCause(Throwable error) { - if (error instanceof CompletionException) { - return error.getCause(); - } - return error; - } -} diff --git a/bolt-api-pooled/src/test/java/org/neo4j/driver/internal/bolt/pooledimpl/PooledBoltConnectionProviderTest.java b/bolt-api-pooled/src/test/java/org/neo4j/driver/internal/bolt/pooledimpl/PooledBoltConnectionProviderTest.java deleted file mode 100644 index 9a6d1cc0f5..0000000000 --- a/bolt-api-pooled/src/test/java/org/neo4j/driver/internal/bolt/pooledimpl/PooledBoltConnectionProviderTest.java +++ /dev/null @@ -1,1013 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.pooledimpl; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.MockitoAnnotations.openMocks; - -import java.time.Clock; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.function.Consumer; -import java.util.function.Supplier; -import java.util.stream.Stream; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.BDDMockito; -import org.mockito.Mock; -import org.mockito.stubbing.Answer; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.AuthInfo; -import org.neo4j.driver.internal.bolt.api.AuthToken; -import org.neo4j.driver.internal.bolt.api.AuthTokens; -import org.neo4j.driver.internal.bolt.api.BoltAgent; -import org.neo4j.driver.internal.bolt.api.BoltConnection; -import org.neo4j.driver.internal.bolt.api.BoltConnectionProvider; -import org.neo4j.driver.internal.bolt.api.BoltConnectionState; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.DatabaseNameUtil; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.MetricsListener; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.ResponseHandler; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; -import org.neo4j.driver.internal.bolt.api.SecurityPlans; -import org.neo4j.driver.internal.bolt.api.exception.MinVersionAcquisitionException; -import org.neo4j.driver.internal.bolt.api.summary.ResetSummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.pooledimpl.impl.PooledBoltConnection; - -class PooledBoltConnectionProviderTest { - PooledBoltConnectionProvider provider; - - @Mock - BoltConnectionProvider upstreamProvider; - - @Mock - LoggingProvider loggingProvider; - - @Mock - Clock clock; - - @Mock - MetricsListener metricsListener; - - @Mock - Consumer databaseNameConsumer; - - @Mock - BoltConnection connection; - - @Mock - Supplier> authTokenStageSupplier; - - final int maxSize = 2; - final long acquisitionTimeout = 5000; - final long maxLifetime = 60000; - final long idleBeforeTest = 30000; - final BoltServerAddress address = BoltServerAddress.LOCAL_DEFAULT; - final RoutingContext context = RoutingContext.EMPTY; - final BoltAgent boltAgent = new BoltAgent("agent", null, null, null); - final String userAgent = "agent"; - final int timeout = 1000; - - final SecurityPlan securityPlan = SecurityPlans.unencrypted(); - final DatabaseName databaseName = DatabaseNameUtil.defaultDatabase(); - final AccessMode mode = AccessMode.WRITE; - final Set bookmarks = Set.of("bookmark1", "bookmark2"); - final BoltProtocolVersion minVersion = new BoltProtocolVersion(5, 6); - final NotificationConfig notificationConfig = NotificationConfig.defaultConfig(); - - @BeforeEach - @SuppressWarnings("resource") - void beforeEach() { - openMocks(this); - given(loggingProvider.getLog(any(Class.class))).willReturn(mock(System.Logger.class)); - given(authTokenStageSupplier.get()) - .willReturn(CompletableFuture.completedStage(AuthTokens.custom(Collections.emptyMap()))); - provider = new PooledBoltConnectionProvider( - upstreamProvider, - maxSize, - acquisitionTimeout, - maxLifetime, - idleBeforeTest, - clock, - loggingProvider, - metricsListener, - address, - context, - boltAgent, - userAgent, - timeout); - } - - @Test - void shouldCreateNewConnection() { - // given - given(upstreamProvider.connect( - eq(address), - eq(context), - eq(boltAgent), - eq(userAgent), - eq(timeout), - eq(securityPlan), - eq(databaseName), - any(), - eq(mode), - eq(bookmarks), - eq(null), - eq(minVersion), - eq(notificationConfig), - any(), - any())) - .willReturn(CompletableFuture.completedStage(connection)); - - // when - var connection = provider.connect( - address, - context, - boltAgent, - userAgent, - timeout, - securityPlan, - databaseName, - authTokenStageSupplier, - mode, - bookmarks, - null, - minVersion, - notificationConfig, - databaseNameConsumer, - Collections.emptyMap()) - .toCompletableFuture() - .join(); - - // then - var pooledConnection = assertInstanceOf(PooledBoltConnection.class, connection); - assertEquals(this.connection, pooledConnection.delegate()); - then(upstreamProvider) - .should() - .connect( - eq(address), - eq(context), - eq(boltAgent), - eq(userAgent), - eq(timeout), - eq(securityPlan), - eq(databaseName), - any(), - eq(mode), - eq(bookmarks), - eq(null), - eq(minVersion), - eq(notificationConfig), - any(), - any()); - assertEquals(1, provider.inUse()); - assertEquals(1, provider.size()); - } - - @Test - void shouldTimeout() { - // given - var acquisitionTimeout = TimeUnit.SECONDS.toMillis(1); - given(upstreamProvider.connect( - eq(address), - eq(context), - eq(boltAgent), - eq(userAgent), - eq(timeout), - eq(securityPlan), - eq(databaseName), - any(), - eq(mode), - eq(bookmarks), - eq(null), - eq(minVersion), - eq(notificationConfig), - any(), - any())) - .willReturn(CompletableFuture.completedStage(connection)); - provider = new PooledBoltConnectionProvider( - upstreamProvider, - 1, - acquisitionTimeout, - maxLifetime, - idleBeforeTest, - clock, - loggingProvider, - metricsListener, - address, - context, - boltAgent, - userAgent, - timeout); - provider.connect( - address, - context, - boltAgent, - userAgent, - timeout, - securityPlan, - databaseName, - authTokenStageSupplier, - mode, - bookmarks, - null, - minVersion, - notificationConfig, - databaseNameConsumer, - Collections.emptyMap()) - .toCompletableFuture() - .join(); - - // when - var connectionStage = provider.connect( - address, - context, - boltAgent, - userAgent, - timeout, - securityPlan, - databaseName, - authTokenStageSupplier, - mode, - bookmarks, - null, - minVersion, - notificationConfig, - databaseNameConsumer, - Collections.emptyMap()); - - // then - var completionException = assertThrows( - CompletionException.class, - () -> connectionStage.toCompletableFuture().join()); - assertInstanceOf(TimeoutException.class, completionException.getCause()); - } - - @Test - void shouldReturnConnectionToPool() { - // given - given(connection.reset()).willReturn(CompletableFuture.completedStage(connection)); - given(connection.flush(any())).willAnswer((Answer>) invocationOnMock -> { - var handler = (ResponseHandler) invocationOnMock.getArgument(0); - handler.onResetSummary(mock(ResetSummary.class)); - handler.onComplete(); - return CompletableFuture.completedStage(null); - }); - given(upstreamProvider.connect( - eq(address), - eq(context), - eq(boltAgent), - eq(userAgent), - eq(timeout), - eq(securityPlan), - eq(databaseName), - any(), - eq(mode), - eq(bookmarks), - eq(null), - eq(minVersion), - eq(notificationConfig), - any(), - any())) - .willReturn(CompletableFuture.completedStage(connection)); - var connection = provider.connect( - address, - context, - boltAgent, - userAgent, - timeout, - securityPlan, - databaseName, - authTokenStageSupplier, - mode, - bookmarks, - null, - minVersion, - notificationConfig, - databaseNameConsumer, - Collections.emptyMap()) - .toCompletableFuture() - .join(); - - // when - connection.close().toCompletableFuture().join(); - - // then - assertEquals(0, provider.inUse()); - assertEquals(1, provider.size()); - } - - @Test - void shouldUseExistingConnection() { - // given - given(connection.reset()).willReturn(CompletableFuture.completedStage(connection)); - given(connection.flush(any())).willAnswer((Answer>) invocationOnMock -> { - var handler = (ResponseHandler) invocationOnMock.getArgument(0); - handler.onResetSummary(mock(ResetSummary.class)); - handler.onComplete(); - return CompletableFuture.completedStage(null); - }); - given(connection.state()).willReturn(BoltConnectionState.OPEN); - given(connection.protocolVersion()).willReturn(minVersion); - var authInfo = mock(AuthInfo.class); - given(authInfo.authAckMillis()).willReturn(0L); - given(authInfo.authToken()).willReturn(AuthTokens.custom(Collections.emptyMap())); - given(connection.authInfo()).willReturn(CompletableFuture.completedStage(authInfo)); - given(upstreamProvider.connect( - eq(address), - eq(context), - eq(boltAgent), - eq(userAgent), - eq(timeout), - eq(securityPlan), - eq(databaseName), - any(), - eq(mode), - eq(bookmarks), - eq(null), - eq(minVersion), - eq(notificationConfig), - any(), - any())) - .willReturn(CompletableFuture.completedStage(connection)); - provider.connect( - address, - context, - boltAgent, - userAgent, - timeout, - securityPlan, - databaseName, - authTokenStageSupplier, - mode, - bookmarks, - null, - minVersion, - notificationConfig, - databaseNameConsumer, - Collections.emptyMap()) - .toCompletableFuture() - .join() - .close() - .toCompletableFuture() - .join(); - BDDMockito.reset(upstreamProvider); - - // when - var connection = provider.connect( - address, - context, - boltAgent, - userAgent, - timeout, - securityPlan, - databaseName, - authTokenStageSupplier, - mode, - bookmarks, - null, - minVersion, - notificationConfig, - databaseNameConsumer, - Collections.emptyMap()) - .toCompletableFuture() - .join(); - - // then - var pooledConnection = assertInstanceOf(PooledBoltConnection.class, connection); - assertEquals(this.connection, pooledConnection.delegate()); - then(upstreamProvider).shouldHaveNoInteractions(); - assertEquals(1, provider.inUse()); - assertEquals(1, provider.size()); - } - - @Test - void shouldClose() { - // given - given(connection.reset()).willReturn(CompletableFuture.completedStage(connection)); - given(connection.flush(any())).willAnswer((Answer>) invocationOnMock -> { - var handler = (ResponseHandler) invocationOnMock.getArgument(0); - handler.onResetSummary(mock(ResetSummary.class)); - handler.onComplete(); - return CompletableFuture.completedStage(null); - }); - given(connection.state()).willReturn(BoltConnectionState.OPEN); - given(connection.close()).willReturn(CompletableFuture.completedStage(null)); - given(upstreamProvider.close()).willReturn(CompletableFuture.completedStage(null)); - given(upstreamProvider.connect( - eq(address), - eq(context), - eq(boltAgent), - eq(userAgent), - eq(timeout), - eq(securityPlan), - eq(databaseName), - any(), - eq(mode), - eq(bookmarks), - eq(null), - eq(minVersion), - eq(notificationConfig), - any(), - any())) - .willReturn(CompletableFuture.completedStage(connection)); - provider.connect( - address, - context, - boltAgent, - userAgent, - timeout, - securityPlan, - databaseName, - authTokenStageSupplier, - mode, - bookmarks, - null, - minVersion, - notificationConfig, - databaseNameConsumer, - Collections.emptyMap()) - .toCompletableFuture() - .join() - .close() - .toCompletableFuture() - .join(); - - // when - provider.close().toCompletableFuture().join(); - - // then - then(connection).should().close(); - then(upstreamProvider).should().close(); - } - - @Test - void shouldVerifyConnectivity() { - // given - given(connection.reset()).willReturn(CompletableFuture.completedStage(connection)); - given(connection.flush(any())).willAnswer((Answer>) invocationOnMock -> { - var handler = (ResponseHandler) invocationOnMock.getArgument(0); - handler.onResetSummary(mock(ResetSummary.class)); - handler.onComplete(); - return CompletableFuture.completedStage(null); - }); - given(upstreamProvider.connect( - eq(address), - eq(context), - eq(boltAgent), - eq(userAgent), - eq(timeout), - eq(securityPlan), - eq(null), - any(), - eq(AccessMode.WRITE), - eq(Collections.emptySet()), - eq(null), - eq(null), - eq(null), - any(), - any())) - .willReturn(CompletableFuture.completedStage(connection)); - - // when - provider.verifyConnectivity( - address, - context, - boltAgent, - userAgent, - timeout, - SecurityPlans.unencrypted(), - AuthTokens.custom(Collections.emptyMap())) - .toCompletableFuture() - .join(); - - // then - then(upstreamProvider) - .should() - .connect( - eq(address), - eq(context), - eq(boltAgent), - eq(userAgent), - eq(timeout), - eq(securityPlan), - eq(null), - any(), - eq(AccessMode.WRITE), - eq(Collections.emptySet()), - eq(null), - eq(null), - eq(null), - any(), - any()); - then(connection).should().reset(); - then(connection).should().flush(any()); - } - - @ParameterizedTest - @MethodSource("supportsMultiDbParams") - void shouldSupportMultiDb(BoltProtocolVersion boltProtocolVersion, boolean expectedToSupport) { - // given - given(connection.protocolVersion()).willReturn(boltProtocolVersion); - given(connection.reset()).willReturn(CompletableFuture.completedStage(connection)); - given(connection.flush(any())).willAnswer((Answer>) invocationOnMock -> { - var handler = (ResponseHandler) invocationOnMock.getArgument(0); - handler.onResetSummary(mock(ResetSummary.class)); - handler.onComplete(); - return CompletableFuture.completedStage(null); - }); - given(upstreamProvider.connect( - eq(address), - eq(context), - eq(boltAgent), - eq(userAgent), - eq(timeout), - eq(securityPlan), - eq(null), - any(), - eq(AccessMode.WRITE), - eq(Collections.emptySet()), - eq(null), - eq(null), - eq(null), - any(), - any())) - .willReturn(CompletableFuture.completedStage(connection)); - - // when - var supports = provider.supportsMultiDb( - address, - context, - boltAgent, - userAgent, - timeout, - SecurityPlans.unencrypted(), - AuthTokens.custom(Collections.emptyMap())) - .toCompletableFuture() - .join(); - - // then - assertEquals(expectedToSupport, supports); - then(upstreamProvider) - .should() - .connect( - eq(address), - eq(context), - eq(boltAgent), - eq(userAgent), - eq(timeout), - eq(securityPlan), - eq(null), - any(), - eq(AccessMode.WRITE), - eq(Collections.emptySet()), - eq(null), - eq(null), - eq(null), - any(), - any()); - then(connection).should().reset(); - then(connection).should().flush(any()); - } - - private static Stream supportsMultiDbParams() { - return Stream.of( - Arguments.arguments(new BoltProtocolVersion(4, 0), true), - Arguments.arguments(new BoltProtocolVersion(3, 5), false)); - } - - @ParameterizedTest - @MethodSource("supportsSessionAuthParams") - void shouldSupportsSessionAuth(BoltProtocolVersion boltProtocolVersion, boolean expectedToSupport) { - // given - given(connection.protocolVersion()).willReturn(boltProtocolVersion); - given(connection.reset()).willReturn(CompletableFuture.completedStage(connection)); - given(connection.flush(any())).willAnswer((Answer>) invocationOnMock -> { - var handler = (ResponseHandler) invocationOnMock.getArgument(0); - handler.onResetSummary(mock(ResetSummary.class)); - handler.onComplete(); - return CompletableFuture.completedStage(null); - }); - given(upstreamProvider.connect( - eq(address), - eq(context), - eq(boltAgent), - eq(userAgent), - eq(timeout), - eq(securityPlan), - eq(null), - any(), - eq(AccessMode.WRITE), - eq(Collections.emptySet()), - eq(null), - eq(null), - eq(null), - any(), - any())) - .willReturn(CompletableFuture.completedStage(connection)); - - // when - var supports = provider.supportsSessionAuth( - address, - context, - boltAgent, - userAgent, - timeout, - SecurityPlans.unencrypted(), - AuthTokens.custom(Collections.emptyMap())) - .toCompletableFuture() - .join(); - - // then - assertEquals(expectedToSupport, supports); - then(upstreamProvider) - .should() - .connect( - eq(address), - eq(context), - eq(boltAgent), - eq(userAgent), - eq(timeout), - eq(securityPlan), - eq(null), - any(), - eq(AccessMode.WRITE), - eq(Collections.emptySet()), - eq(null), - eq(null), - eq(null), - any(), - any()); - then(connection).should().reset(); - then(connection).should().flush(any()); - } - - private static Stream supportsSessionAuthParams() { - return Stream.of( - Arguments.arguments(new BoltProtocolVersion(5, 1), true), - Arguments.arguments(new BoltProtocolVersion(5, 0), false)); - } - - @Test - void shouldThrowOnLowerVersion() { - // given - given(connection.protocolVersion()).willReturn(new BoltProtocolVersion(5, 0)); - given(connection.state()).willReturn(BoltConnectionState.OPEN); - given(connection.reset()).willReturn(CompletableFuture.completedStage(connection)); - given(connection.flush(any())).willAnswer((Answer>) invocationOnMock -> { - var handler = (ResponseHandler) invocationOnMock.getArgument(0); - handler.onResetSummary(mock(ResetSummary.class)); - handler.onComplete(); - return CompletableFuture.completedStage(null); - }); - given(upstreamProvider.connect( - eq(address), - eq(context), - eq(boltAgent), - eq(userAgent), - eq(timeout), - eq(securityPlan), - eq(databaseName), - any(), - eq(mode), - eq(bookmarks), - eq(null), - eq(minVersion), - eq(notificationConfig), - any(), - any())) - .willReturn(CompletableFuture.completedStage(connection)); - provider.connect( - address, - context, - boltAgent, - userAgent, - timeout, - securityPlan, - databaseName, - authTokenStageSupplier, - mode, - bookmarks, - null, - minVersion, - notificationConfig, - databaseNameConsumer, - Collections.emptyMap()) - .toCompletableFuture() - .join() - .close() - .toCompletableFuture() - .join(); - - // when - var future = provider.connect( - address, - context, - boltAgent, - userAgent, - timeout, - securityPlan, - databaseName, - authTokenStageSupplier, - mode, - bookmarks, - null, - new BoltProtocolVersion(5, 5), - NotificationConfig.defaultConfig(), - databaseNameConsumer, - Collections.emptyMap()) - .toCompletableFuture(); - - // then - var exception = assertThrows(CompletionException.class, future::join); - assertInstanceOf(MinVersionAcquisitionException.class, exception.getCause()); - } - - @Test - void shouldTestMaxLifetime() { - // given - given(connection.protocolVersion()).willReturn(minVersion); - given(connection.state()).willReturn(BoltConnectionState.OPEN); - given(connection.reset()).willReturn(CompletableFuture.completedStage(connection)); - given(connection.flush(any())).willAnswer((Answer>) invocationOnMock -> { - var handler = (ResponseHandler) invocationOnMock.getArgument(0); - handler.onResetSummary(mock(ResetSummary.class)); - handler.onComplete(); - return CompletableFuture.completedStage(null); - }); - var connection2 = mock(BoltConnection.class); - given(upstreamProvider.connect( - eq(address), - eq(context), - eq(boltAgent), - eq(userAgent), - eq(timeout), - eq(securityPlan), - eq(databaseName), - any(), - eq(mode), - eq(bookmarks), - eq(null), - eq(minVersion), - eq(notificationConfig), - any(), - any())) - .willReturn(CompletableFuture.completedStage(connection)) - .willReturn(CompletableFuture.completedStage(connection2)); - provider.connect( - address, - context, - boltAgent, - userAgent, - timeout, - securityPlan, - databaseName, - authTokenStageSupplier, - mode, - bookmarks, - null, - minVersion, - notificationConfig, - databaseNameConsumer, - Collections.emptyMap()) - .toCompletableFuture() - .join() - .close() - .toCompletableFuture() - .join(); - given(clock.millis()).willReturn(maxLifetime + 1); - - // when - var anotherConnection = provider.connect( - address, - context, - boltAgent, - userAgent, - timeout, - securityPlan, - databaseName, - authTokenStageSupplier, - mode, - bookmarks, - null, - minVersion, - NotificationConfig.defaultConfig(), - databaseNameConsumer, - Collections.emptyMap()) - .toCompletableFuture() - .join(); - - // then - assertEquals(1, provider.inUse()); - assertEquals(1, provider.size()); - assertEquals(connection2, ((PooledBoltConnection) anotherConnection).delegate()); - then(connection).should().close(); - } - - @Test - void shouldTestLiveness() { - // given - given(connection.protocolVersion()).willReturn(minVersion); - given(connection.state()).willReturn(BoltConnectionState.OPEN); - given(connection.reset()).willReturn(CompletableFuture.completedStage(connection)); - given(connection.flush(any())).willAnswer((Answer>) invocationOnMock -> { - var handler = (ResponseHandler) invocationOnMock.getArgument(0); - handler.onResetSummary(mock(ResetSummary.class)); - handler.onComplete(); - return CompletableFuture.completedStage(null); - }); - var authInfo = mock(AuthInfo.class); - given(authInfo.authAckMillis()).willReturn(0L); - given(authInfo.authToken()).willReturn(AuthTokens.custom(Collections.emptyMap())); - given(connection.authInfo()).willReturn(CompletableFuture.completedStage(authInfo)); - given(upstreamProvider.connect( - eq(address), - eq(context), - eq(boltAgent), - eq(userAgent), - eq(timeout), - eq(securityPlan), - eq(databaseName), - any(), - eq(mode), - eq(bookmarks), - eq(null), - eq(minVersion), - eq(notificationConfig), - any(), - any())) - .willReturn(CompletableFuture.completedStage(connection)); - provider.connect( - address, - context, - boltAgent, - userAgent, - timeout, - securityPlan, - databaseName, - authTokenStageSupplier, - mode, - bookmarks, - null, - minVersion, - notificationConfig, - databaseNameConsumer, - Collections.emptyMap()) - .toCompletableFuture() - .join() - .close() - .toCompletableFuture() - .join(); - given(clock.millis()).willReturn(idleBeforeTest + 1); - - // when - var actualConnection = provider.connect( - address, - context, - boltAgent, - userAgent, - timeout, - securityPlan, - databaseName, - authTokenStageSupplier, - mode, - bookmarks, - null, - minVersion, - NotificationConfig.defaultConfig(), - databaseNameConsumer, - Collections.emptyMap()) - .toCompletableFuture() - .join(); - - // then - assertEquals(connection, ((PooledBoltConnection) actualConnection).delegate()); - then(connection).should(times(2)).reset(); - then(connection).should(times(2)).flush(any()); - } - - @Test - void shouldPipelineReauth() { - // given - given(connection.protocolVersion()).willReturn(minVersion); - given(connection.state()).willReturn(BoltConnectionState.OPEN); - given(connection.reset()).willReturn(CompletableFuture.completedStage(connection)); - given(connection.flush(any())).willAnswer((Answer>) invocationOnMock -> { - var handler = (ResponseHandler) invocationOnMock.getArgument(0); - handler.onResetSummary(mock(ResetSummary.class)); - handler.onComplete(); - return CompletableFuture.completedStage(null); - }); - given(connection.logoff()).willReturn(CompletableFuture.completedStage(connection)); - var authMap = Map.of("key", mock(Value.class)); - var authToken = AuthTokens.custom(authMap); - given(connection.logon(authToken)).willReturn(CompletableFuture.completedStage(connection)); - var authInfo = mock(AuthInfo.class); - given(authInfo.authAckMillis()).willReturn(0L); - given(authInfo.authToken()).willReturn(AuthTokens.custom(Collections.emptyMap())); - given(connection.authInfo()).willReturn(CompletableFuture.completedStage(authInfo)); - given(authTokenStageSupplier.get()) - .willReturn(CompletableFuture.completedStage(AuthTokens.custom(Collections.emptyMap()))) - .willReturn(CompletableFuture.completedStage(authToken)); - given(upstreamProvider.connect( - eq(address), - eq(context), - eq(boltAgent), - eq(userAgent), - eq(timeout), - eq(securityPlan), - eq(databaseName), - any(), - eq(mode), - eq(bookmarks), - eq(null), - eq(minVersion), - eq(notificationConfig), - any(), - any())) - .willReturn(CompletableFuture.completedStage(connection)); - provider.connect( - address, - context, - boltAgent, - userAgent, - timeout, - securityPlan, - databaseName, - authTokenStageSupplier, - mode, - bookmarks, - null, - minVersion, - notificationConfig, - databaseNameConsumer, - Collections.emptyMap()) - .toCompletableFuture() - .join() - .close() - .toCompletableFuture() - .join(); - - // when - var actualConnection = provider.connect( - address, - context, - boltAgent, - userAgent, - timeout, - securityPlan, - databaseName, - authTokenStageSupplier, - mode, - bookmarks, - null, - minVersion, - NotificationConfig.defaultConfig(), - databaseNameConsumer, - Collections.emptyMap()) - .toCompletableFuture() - .join(); - - // then - assertEquals(connection, ((PooledBoltConnection) actualConnection).delegate()); - then(connection).should().logoff(); - then(connection).should().logon(authToken); - } -} diff --git a/bolt-api-routed/LICENSES.txt b/bolt-api-routed/LICENSES.txt deleted file mode 100644 index f8e0fd3292..0000000000 --- a/bolt-api-routed/LICENSES.txt +++ /dev/null @@ -1,5 +0,0 @@ -This file contains the full license text of the included third party -libraries. For an overview of the licenses see the NOTICE.txt file. - - - diff --git a/bolt-api-routed/NOTICE.txt b/bolt-api-routed/NOTICE.txt deleted file mode 100644 index c3bf48c6fc..0000000000 --- a/bolt-api-routed/NOTICE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) "Neo4j" -Neo4j Sweden AB [https://neo4j.com] - -This file is part of Neo4j. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -Full license texts are found in LICENSES.txt. - - -Third-party licenses --------------------- - diff --git a/bolt-api-routed/pom.xml b/bolt-api-routed/pom.xml deleted file mode 100644 index 929a7bf1e7..0000000000 --- a/bolt-api-routed/pom.xml +++ /dev/null @@ -1,70 +0,0 @@ - - 4.0.0 - - - org.neo4j.driver - neo4j-java-driver-parent - 5.28-SNAPSHOT - - - neo4j-bolt-api-routed - - jar - Neo4j Bolt API Routed - https://github.com/neo4j/neo4j-java-driver - - - ${project.basedir}/.. - ,-try - - - - - org.neo4j.driver - neo4j-bolt-api - ${project.version} - - - - org.mockito - mockito-core - - - org.junit.jupiter - junit-jupiter - - - - - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-javadoc-plugin - - - org.apache.maven.plugins - maven-failsafe-plugin - - - org.apache.maven.surefire - surefire-junit-platform - ${surefire.and.failsafe.version} - - - - - - - - scm:git:git://github.com/neo4j/neo4j-java-driver.git - scm:git:git@github.com:neo4j/neo4j-java-driver.git - https://github.com/neo4j/neo4j-java-driver - - - diff --git a/bolt-api-routed/src/main/java/module-info.java b/bolt-api-routed/src/main/java/module-info.java deleted file mode 100644 index d1f43f7b56..0000000000 --- a/bolt-api-routed/src/main/java/module-info.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * The Neo4j Bolt API routed implementation module. - */ -module org.neo4j.bolt.routed { - exports org.neo4j.driver.internal.bolt.routedimpl; - - requires transitive org.neo4j.bolt.api; -} diff --git a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/ClusterCompositionLookupResult.java b/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/ClusterCompositionLookupResult.java deleted file mode 100644 index 33fe1bfc4b..0000000000 --- a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/ClusterCompositionLookupResult.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl; - -import java.util.Optional; -import java.util.Set; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.ClusterComposition; - -public class ClusterCompositionLookupResult { - private final ClusterComposition composition; - - private final Set resolvedInitialRouters; - - public ClusterCompositionLookupResult(ClusterComposition composition) { - this(composition, null); - } - - public ClusterCompositionLookupResult( - ClusterComposition composition, Set resolvedInitialRouters) { - this.composition = composition; - this.resolvedInitialRouters = resolvedInitialRouters; - } - - public ClusterComposition getClusterComposition() { - return composition; - } - - public Optional> getResolvedInitialRouters() { - return Optional.ofNullable(resolvedInitialRouters); - } -} diff --git a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/Rediscovery.java b/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/Rediscovery.java deleted file mode 100644 index 258de5c663..0000000000 --- a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/Rediscovery.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl; - -import java.net.UnknownHostException; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CompletionStage; -import java.util.function.Function; -import java.util.function.Supplier; -import org.neo4j.driver.internal.bolt.api.AuthToken; -import org.neo4j.driver.internal.bolt.api.BoltConnectionProvider; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; - -/** - * Provides cluster composition lookup capabilities and initial router address resolution. - */ -public interface Rediscovery { - CompletionStage lookupClusterComposition( - SecurityPlan securityPlan, - RoutingTable routingTable, - Function connectionProviderGetter, - Set bookmarks, - String impersonatedUser, - Supplier> authTokenStageSupplier, - BoltProtocolVersion minVersion); - - List resolve() throws UnknownHostException; -} diff --git a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/RoutedBoltConnectionProvider.java b/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/RoutedBoltConnectionProvider.java deleted file mode 100644 index ad0024de14..0000000000 --- a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/RoutedBoltConnectionProvider.java +++ /dev/null @@ -1,518 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl; - -import static java.lang.String.format; - -import java.time.Clock; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; -import javax.net.ssl.SSLHandshakeException; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.AuthToken; -import org.neo4j.driver.internal.bolt.api.BoltAgent; -import org.neo4j.driver.internal.bolt.api.BoltConnection; -import org.neo4j.driver.internal.bolt.api.BoltConnectionProvider; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.DatabaseNameUtil; -import org.neo4j.driver.internal.bolt.api.DomainNameResolver; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.MetricsListener; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; -import org.neo4j.driver.internal.bolt.api.exception.BoltConnectionAcquisitionException; -import org.neo4j.driver.internal.bolt.api.exception.BoltFailureException; -import org.neo4j.driver.internal.bolt.api.exception.BoltServiceUnavailableException; -import org.neo4j.driver.internal.bolt.routedimpl.impl.AuthTokenManagerExecutionException; -import org.neo4j.driver.internal.bolt.routedimpl.impl.RoutedBoltConnection; -import org.neo4j.driver.internal.bolt.routedimpl.impl.cluster.RediscoveryImpl; -import org.neo4j.driver.internal.bolt.routedimpl.impl.cluster.RoutingTableHandler; -import org.neo4j.driver.internal.bolt.routedimpl.impl.cluster.RoutingTableRegistry; -import org.neo4j.driver.internal.bolt.routedimpl.impl.cluster.RoutingTableRegistryImpl; -import org.neo4j.driver.internal.bolt.routedimpl.impl.cluster.loadbalancing.LeastConnectedLoadBalancingStrategy; -import org.neo4j.driver.internal.bolt.routedimpl.impl.cluster.loadbalancing.LoadBalancingStrategy; -import org.neo4j.driver.internal.bolt.routedimpl.impl.util.FutureUtil; - -public class RoutedBoltConnectionProvider implements BoltConnectionProvider { - private static final String CONNECTION_ACQUISITION_COMPLETION_FAILURE_MESSAGE = - "Connection acquisition failed for all available addresses."; - private static final String CONNECTION_ACQUISITION_COMPLETION_EXCEPTION_MESSAGE = - "Failed to obtain connection towards %s server. Known routing table is: %s"; - private static final String CONNECTION_ACQUISITION_ATTEMPT_FAILURE_MESSAGE = - "Failed to obtain a connection towards address %s, will try other addresses if available. Complete failure is reported separately from this entry."; - private final System.Logger log; - private final Function boltConnectionProviderFunction; - private final Map addressToProvider = new HashMap<>(); - private final Map addressToInUseCount = new HashMap<>(); - private final LoadBalancingStrategy loadBalancingStrategy; - private final RoutingTableRegistry registry; - private final RoutingContext routingContext; - private final BoltAgent boltAgent; - private final String userAgent; - private final int connectTimeoutMillis; - - private Rediscovery rediscovery; - private CompletableFuture closeFuture; - - public RoutedBoltConnectionProvider( - Function boltConnectionProviderFunction, - Function> resolver, - DomainNameResolver domainNameResolver, - long routingTablePurgeDelayMs, - Rediscovery rediscovery, - Clock clock, - LoggingProvider logging, - BoltServerAddress address, - RoutingContext routingContext, - BoltAgent boltAgent, - String userAgent, - int connectTimeoutMillis, - MetricsListener metricsListener) { - this.boltConnectionProviderFunction = Objects.requireNonNull(boltConnectionProviderFunction); - this.log = logging.getLog(getClass()); - this.loadBalancingStrategy = new LeastConnectedLoadBalancingStrategy(this::getInUseCount, logging); - this.rediscovery = rediscovery; - this.routingContext = routingContext; - this.boltAgent = boltAgent; - this.userAgent = userAgent; - this.connectTimeoutMillis = connectTimeoutMillis; - if (this.rediscovery == null) { - this.rediscovery = new RediscoveryImpl( - address, - resolver, - logging, - domainNameResolver, - routingContext, - boltAgent, - userAgent, - connectTimeoutMillis); - } - this.registry = new RoutingTableRegistryImpl( - this::get, this.rediscovery, clock, logging, routingTablePurgeDelayMs, this::shutdownUnusedProviders); - } - - @Override - public CompletionStage connect( - BoltServerAddress ignoredAddress, - RoutingContext ignoredRoutingContext, - BoltAgent ignoredBoltAgent, - String ignoredUserAgent, - int ignoredConnectTimeoutMillis, - SecurityPlan securityPlan, - DatabaseName databaseName, - Supplier> authTokenStageSupplier, - AccessMode mode, - Set bookmarks, - String impersonatedUser, - BoltProtocolVersion minVersion, - NotificationConfig notificationConfig, - Consumer databaseNameConsumer, - Map additionalParameters) { - RoutingTableRegistry registry; - var homeDatabaseHintObj = additionalParameters.get("homeDatabase"); - var homeDatabaseHint = homeDatabaseHintObj instanceof String ? (String) homeDatabaseHintObj : null; - synchronized (this) { - if (closeFuture != null) { - return CompletableFuture.failedFuture(new IllegalStateException("Connection provider is closed.")); - } - registry = this.registry; - } - - Supplier> supplier = - () -> authTokenStageSupplier.get().exceptionally(throwable -> { - throw new AuthTokenManagerExecutionException(throwable); - }); - - var handlerRef = new AtomicReference(); - var databaseNameFuture = databaseName == null - ? new CompletableFuture() - : CompletableFuture.completedFuture(databaseName); - databaseNameFuture.whenComplete((name, throwable) -> { - if (name != null) { - databaseNameConsumer.accept(name); - } - }); - return registry.ensureRoutingTable( - securityPlan, - databaseNameFuture, - mode, - bookmarks, - impersonatedUser, - supplier, - minVersion, - homeDatabaseHint) - .thenApply(routingTableHandler -> { - handlerRef.set(routingTableHandler); - return routingTableHandler; - }) - .thenCompose(routingTableHandler -> acquire( - securityPlan, - mode, - routingTableHandler.routingTable(), - supplier, - routingTableHandler.routingTable().database(), - Set.of(), - impersonatedUser, - minVersion, - notificationConfig)) - .thenApply(boltConnection -> - (BoltConnection) new RoutedBoltConnection(boltConnection, handlerRef.get(), mode, this)) - .exceptionally(throwable -> { - throwable = FutureUtil.completionExceptionCause(throwable); - if (throwable instanceof AuthTokenManagerExecutionException) { - throwable = throwable.getCause(); - } - if (throwable instanceof RuntimeException runtimeException) { - throw runtimeException; - } else { - throw new CompletionException(throwable); - } - }); - } - - @Override - public CompletionStage verifyConnectivity( - BoltServerAddress ignoredAddress, - RoutingContext ignoredRoutingContext, - BoltAgent ignoredBoltAgent, - String ignoredUserAgent, - int ignoredConnectTimeoutMillis, - SecurityPlan securityPlan, - AuthToken authToken) { - RoutingTableRegistry registry; - synchronized (this) { - registry = this.registry; - } - return supportsMultiDb(null, null, null, null, 0, securityPlan, authToken) - .thenCompose(supports -> registry.ensureRoutingTable( - securityPlan, - supports - ? CompletableFuture.completedFuture(DatabaseNameUtil.database("system")) - : CompletableFuture.completedFuture(DatabaseNameUtil.defaultDatabase()), - AccessMode.READ, - Collections.emptySet(), - null, - () -> CompletableFuture.completedStage(authToken), - null, - null)) - .handle((ignored, error) -> { - if (error != null) { - var cause = FutureUtil.completionExceptionCause(error); - if (cause instanceof BoltServiceUnavailableException) { - throw FutureUtil.asCompletionException(new BoltServiceUnavailableException( - "Unable to connect to database management service, ensure the database is running and that there is a working network connection to it.", - cause)); - } - throw FutureUtil.asCompletionException(cause); - } - return null; - }); - } - - @Override - public CompletionStage supportsMultiDb( - BoltServerAddress ignoredAddress, - RoutingContext ignoredRoutingContext, - BoltAgent ignoredBoltAgent, - String ignoredUserAgent, - int ignoredConnectTimeoutMillis, - SecurityPlan securityPlan, - AuthToken authToken) { - return detectFeature( - securityPlan, - authToken, - "Failed to perform multi-databases feature detection with the following servers: ", - (boltConnection -> boltConnection.protocolVersion().compareTo(new BoltProtocolVersion(4, 0)) >= 0)); - } - - @Override - public CompletionStage supportsSessionAuth( - BoltServerAddress ignoredAddress, - RoutingContext ignoredRoutingContext, - BoltAgent ignoredBoltAgent, - String ignoredUserAgent, - int ignoredConnectTimeoutMillis, - SecurityPlan securityPlan, - AuthToken authToken) { - return detectFeature( - securityPlan, - authToken, - "Failed to perform session auth feature detection with the following servers: ", - (boltConnection -> new BoltProtocolVersion(5, 1).compareTo(boltConnection.protocolVersion()) <= 0)); - } - - private synchronized void shutdownUnusedProviders(Set addressesToRetain) { - var iterator = addressToProvider.entrySet().iterator(); - while (iterator.hasNext()) { - var entry = iterator.next(); - var address = entry.getKey(); - if (!addressesToRetain.contains(address) && getInUseCount(address) == 0) { - entry.getValue().close(); - iterator.remove(); - } - } - } - - private CompletionStage detectFeature( - SecurityPlan securityPlan, - AuthToken authToken, - String baseErrorMessagePrefix, - Function featureDetectionFunction) { - Rediscovery rediscovery; - synchronized (this) { - rediscovery = this.rediscovery; - } - - List addresses; - try { - addresses = rediscovery.resolve(); - } catch (Throwable error) { - return CompletableFuture.failedFuture(error); - } - CompletableFuture result = CompletableFuture.completedFuture(null); - Throwable baseError = new BoltServiceUnavailableException(baseErrorMessagePrefix + addresses); - - Function isSecurityException = - boltFailureException -> boltFailureException.code().startsWith("Neo.ClientError.Security."); - - for (var address : addresses) { - result = FutureUtil.onErrorContinue(result, baseError, completionError -> { - // We fail fast on security errors - var error = FutureUtil.completionExceptionCause(completionError); - if (error instanceof BoltFailureException boltFailureException) { - if (isSecurityException.apply(boltFailureException)) { - return CompletableFuture.failedFuture(error); - } - } else if (error instanceof SSLHandshakeException) { - return CompletableFuture.failedFuture(error); - } - return get(address) - .connect( - address, - routingContext, - boltAgent, - userAgent, - connectTimeoutMillis, - securityPlan, - null, - () -> CompletableFuture.completedStage(authToken), - AccessMode.WRITE, - Collections.emptySet(), - null, - null, - null, - (ignored) -> {}, - Collections.emptyMap()) - .thenCompose(boltConnection -> { - var featureDetected = featureDetectionFunction.apply(boltConnection); - return boltConnection.close().thenApply(ignored -> featureDetected); - }); - }); - } - return FutureUtil.onErrorContinue(result, baseError, completionError -> { - // If we failed with security errors, then we rethrow the security error out, otherwise we throw the chained - // errors. - var error = FutureUtil.completionExceptionCause(completionError); - if (error instanceof BoltFailureException boltFailureException) { - if (isSecurityException.apply(boltFailureException)) { - return CompletableFuture.failedFuture(error); - } - } else if (error instanceof SSLHandshakeException) { - return CompletableFuture.failedFuture(error); - } - return CompletableFuture.failedFuture(baseError); - }); - } - - private CompletionStage acquire( - SecurityPlan securityPlan, - AccessMode mode, - RoutingTable routingTable, - Supplier> authTokenStageSupplier, - DatabaseName database, - Set bookmarks, - String impersonatedUser, - BoltProtocolVersion minVersion, - NotificationConfig notificationConfig) { - var result = new CompletableFuture(); - List attemptExceptions = new ArrayList<>(); - acquire( - securityPlan, - mode, - routingTable, - result, - authTokenStageSupplier, - attemptExceptions, - database, - bookmarks, - impersonatedUser, - minVersion, - notificationConfig); - return result; - } - - private void acquire( - SecurityPlan securityPlan, - AccessMode mode, - RoutingTable routingTable, - CompletableFuture result, - Supplier> authTokenStageSupplier, - List attemptErrors, - DatabaseName database, - Set bookmarks, - String impersonatedUser, - BoltProtocolVersion minVersion, - NotificationConfig notificationConfig) { - var addresses = getAddressesByMode(mode, routingTable); - log.log(System.Logger.Level.DEBUG, "Addresses: " + addresses); - var address = selectAddress(mode, addresses); - log.log(System.Logger.Level.DEBUG, "Selected address: " + address); - - if (address == null) { - var completionError = new BoltConnectionAcquisitionException( - format(CONNECTION_ACQUISITION_COMPLETION_EXCEPTION_MESSAGE, mode, routingTable)); - attemptErrors.forEach(completionError::addSuppressed); - log.log(System.Logger.Level.ERROR, CONNECTION_ACQUISITION_COMPLETION_FAILURE_MESSAGE, completionError); - result.completeExceptionally(completionError); - return; - } - - get(address) - .connect( - address, - routingContext, - boltAgent, - userAgent, - connectTimeoutMillis, - securityPlan, - database, - authTokenStageSupplier, - mode, - bookmarks, - impersonatedUser, - minVersion, - notificationConfig, - (ignored) -> {}, - Collections.emptyMap()) - .whenComplete((connection, completionError) -> { - var error = FutureUtil.completionExceptionCause(completionError); - if (error != null) { - if (error instanceof BoltServiceUnavailableException) { - var attemptMessage = format(CONNECTION_ACQUISITION_ATTEMPT_FAILURE_MESSAGE, address); - log.log(System.Logger.Level.WARNING, attemptMessage); - log.log(System.Logger.Level.DEBUG, attemptMessage, error); - attemptErrors.add(error); - routingTable.forget(address); - CompletableFuture.runAsync(() -> acquire( - securityPlan, - mode, - routingTable, - result, - authTokenStageSupplier, - attemptErrors, - database, - bookmarks, - impersonatedUser, - minVersion, - notificationConfig)); - } else { - result.completeExceptionally(error); - } - } else { - incrementInUseCount(address); - result.complete(connection); - } - }); - } - - private BoltServerAddress selectAddress(AccessMode mode, List addresses) { - return switch (mode) { - case READ -> loadBalancingStrategy.selectReader(addresses); - case WRITE -> loadBalancingStrategy.selectWriter(addresses); - }; - } - - private static List getAddressesByMode(AccessMode mode, RoutingTable routingTable) { - return switch (mode) { - case READ -> routingTable.readers(); - case WRITE -> routingTable.writers(); - }; - } - - private synchronized int getInUseCount(BoltServerAddress address) { - return addressToInUseCount.getOrDefault(address, 0); - } - - private synchronized void incrementInUseCount(BoltServerAddress address) { - addressToInUseCount.merge(address, 1, Integer::sum); - } - - public synchronized void decrementInUseCount(BoltServerAddress address) { - addressToInUseCount.compute(address, (ignored, value) -> { - if (value == null) { - return null; - } else { - value--; - return value > 0 ? value : null; - } - }); - } - - @Override - public CompletionStage close() { - CompletableFuture closeFuture; - synchronized (this) { - if (this.closeFuture == null) { - @SuppressWarnings({"rawtypes", "RedundantSuppression"}) - var futures = new CompletableFuture[addressToProvider.size()]; - var iterator = addressToProvider.values().iterator(); - var index = 0; - while (iterator.hasNext()) { - futures[index++] = iterator.next().close().toCompletableFuture(); - iterator.remove(); - } - this.closeFuture = CompletableFuture.allOf(futures); - } - closeFuture = this.closeFuture; - } - return closeFuture; - } - - private synchronized BoltConnectionProvider get(BoltServerAddress address) { - var provider = addressToProvider.get(address); - if (provider == null) { - provider = boltConnectionProviderFunction.apply(address); - addressToProvider.put(address, provider); - } - return provider; - } -} diff --git a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/RoutingTable.java b/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/RoutingTable.java deleted file mode 100644 index 4691e31bbe..0000000000 --- a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/RoutingTable.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl; - -import java.util.List; -import java.util.Set; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.ClusterComposition; -import org.neo4j.driver.internal.bolt.api.DatabaseName; - -public interface RoutingTable { - boolean isStaleFor(AccessMode mode); - - boolean hasBeenStaleFor(long staleRoutingTableTimeout); - - void update(ClusterComposition cluster); - - void forget(BoltServerAddress address); - - /** - * Returns an immutable list of reader addresses. - * - * @return the immutable list of reader addresses. - */ - List readers(); - - /** - * Returns an immutable list of writer addresses. - * - * @return the immutable list of write addresses. - */ - List writers(); - - /** - * Returns an immutable list of router addresses. - * - * @return the immutable list of router addresses. - */ - List routers(); - - /** - * Returns an immutable unordered set of all addresses known by this routing table. This includes all router, reader, writer and disused addresses. - * - * @return the immutable set of all addresses. - */ - Set servers(); - - DatabaseName database(); - - void forgetWriter(BoltServerAddress toRemove); - - void replaceRouterIfPresent(BoltServerAddress oldRouter, BoltServerAddress newRouter); - - boolean preferInitialRouter(); - - long expirationTimestamp(); -} diff --git a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/AuthTokenManagerExecutionException.java b/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/AuthTokenManagerExecutionException.java deleted file mode 100644 index 37dcc729ed..0000000000 --- a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/AuthTokenManagerExecutionException.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl; - -import java.io.Serial; - -public class AuthTokenManagerExecutionException extends RuntimeException { - @Serial - private static final long serialVersionUID = -7415186795248189131L; - - public AuthTokenManagerExecutionException(Throwable cause) { - super(cause); - } -} diff --git a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/RoutedBoltConnection.java b/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/RoutedBoltConnection.java deleted file mode 100644 index 7127896c6d..0000000000 --- a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/RoutedBoltConnection.java +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl; - -import static java.lang.String.format; - -import java.time.Duration; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.CompletionStage; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.AuthInfo; -import org.neo4j.driver.internal.bolt.api.AuthToken; -import org.neo4j.driver.internal.bolt.api.BoltConnection; -import org.neo4j.driver.internal.bolt.api.BoltConnectionState; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.ResponseHandler; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; -import org.neo4j.driver.internal.bolt.api.TransactionType; -import org.neo4j.driver.internal.bolt.api.exception.BoltFailureException; -import org.neo4j.driver.internal.bolt.api.exception.BoltServiceUnavailableException; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.CommitSummary; -import org.neo4j.driver.internal.bolt.api.summary.DiscardSummary; -import org.neo4j.driver.internal.bolt.api.summary.LogoffSummary; -import org.neo4j.driver.internal.bolt.api.summary.LogonSummary; -import org.neo4j.driver.internal.bolt.api.summary.PullSummary; -import org.neo4j.driver.internal.bolt.api.summary.ResetSummary; -import org.neo4j.driver.internal.bolt.api.summary.RollbackSummary; -import org.neo4j.driver.internal.bolt.api.summary.RouteSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.summary.TelemetrySummary; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.routedimpl.RoutedBoltConnectionProvider; -import org.neo4j.driver.internal.bolt.routedimpl.impl.cluster.RoutingTableHandler; -import org.neo4j.driver.internal.bolt.routedimpl.impl.util.FutureUtil; - -public class RoutedBoltConnection implements BoltConnection { - private final BoltConnection delegate; - private final RoutingTableHandler routingTableHandler; - private final AccessMode accessMode; - private final RoutedBoltConnectionProvider provider; - - public RoutedBoltConnection( - BoltConnection delegate, - RoutingTableHandler routingTableHandler, - AccessMode accessMode, - RoutedBoltConnectionProvider provider) { - this.delegate = Objects.requireNonNull(delegate); - this.routingTableHandler = Objects.requireNonNull(routingTableHandler); - this.accessMode = Objects.requireNonNull(accessMode); - this.provider = Objects.requireNonNull(provider); - } - - @Override - public CompletionStage onLoop() { - return delegate.onLoop(); - } - - @Override - public CompletionStage route( - DatabaseName databaseName, String impersonatedUser, Set bookmarks) { - return delegate.route(databaseName, impersonatedUser, bookmarks).thenApply(ignored -> this); - } - - @Override - public CompletionStage beginTransaction( - DatabaseName databaseName, - AccessMode accessMode, - String impersonatedUser, - Set bookmarks, - TransactionType transactionType, - Duration txTimeout, - Map txMetadata, - String txType, - NotificationConfig notificationConfig) { - return delegate.beginTransaction( - databaseName, - accessMode, - impersonatedUser, - bookmarks, - transactionType, - txTimeout, - txMetadata, - txType, - notificationConfig) - .thenApply(ignored -> this); - } - - @Override - public CompletionStage runInAutoCommitTransaction( - DatabaseName databaseName, - AccessMode accessMode, - String impersonatedUser, - Set bookmarks, - String query, - Map parameters, - Duration txTimeout, - Map txMetadata, - NotificationConfig notificationConfig) { - return delegate.runInAutoCommitTransaction( - databaseName, - accessMode, - impersonatedUser, - bookmarks, - query, - parameters, - txTimeout, - txMetadata, - notificationConfig) - .thenApply(ignored -> this); - } - - @Override - public CompletionStage run(String query, Map parameters) { - return delegate.run(query, parameters).thenApply(ignored -> this); - } - - @Override - public CompletionStage pull(long qid, long request) { - return delegate.pull(qid, request).thenApply(ignored -> this); - } - - @Override - public CompletionStage discard(long qid, long number) { - return delegate.discard(qid, number).thenApply(ignored -> this); - } - - @Override - public CompletionStage commit() { - return delegate.commit().thenApply(ignored -> this); - } - - @Override - public CompletionStage rollback() { - return delegate.rollback().thenApply(ignored -> this); - } - - @Override - public CompletionStage reset() { - return delegate.reset().thenApply(ignored -> this); - } - - @Override - public CompletionStage logoff() { - return delegate.logoff().thenApply(ignored -> this); - } - - @Override - public CompletionStage logon(AuthToken authToken) { - return delegate.logon(authToken).thenApply(ignored -> this); - } - - @Override - public CompletionStage telemetry(TelemetryApi telemetryApi) { - return delegate.telemetry(telemetryApi).thenApply(ignored -> this); - } - - @Override - public CompletionStage clear() { - return delegate.clear(); - } - - @Override - public CompletionStage flush(ResponseHandler handler) { - return delegate.flush(new ResponseHandler() { - boolean notifyHandler = true; - - @Override - public void onError(Throwable throwable) { - handler.onError(handledError(throwable, notifyHandler)); - notifyHandler = false; - } - - @Override - public void onBeginSummary(BeginSummary summary) { - handler.onBeginSummary(summary); - } - - @Override - public void onRunSummary(RunSummary summary) { - handler.onRunSummary(summary); - } - - @Override - public void onRecord(Value[] fields) { - handler.onRecord(fields); - } - - @Override - public void onPullSummary(PullSummary summary) { - handler.onPullSummary(summary); - } - - @Override - public void onDiscardSummary(DiscardSummary summary) { - handler.onDiscardSummary(summary); - } - - @Override - public void onCommitSummary(CommitSummary summary) { - handler.onCommitSummary(summary); - } - - @Override - public void onRollbackSummary(RollbackSummary summary) { - handler.onRollbackSummary(summary); - } - - @Override - public void onResetSummary(ResetSummary summary) { - handler.onResetSummary(summary); - } - - @Override - public void onRouteSummary(RouteSummary summary) { - handler.onRouteSummary(summary); - } - - @Override - public void onLogoffSummary(LogoffSummary summary) { - handler.onLogoffSummary(summary); - } - - @Override - public void onLogonSummary(LogonSummary summary) { - handler.onLogonSummary(summary); - } - - @Override - public void onTelemetrySummary(TelemetrySummary summary) { - handler.onTelemetrySummary(summary); - } - - @Override - public void onIgnored() { - handler.onIgnored(); - } - - @Override - public void onComplete() { - handler.onComplete(); - } - }); - } - - @Override - public CompletionStage forceClose(String reason) { - return delegate.forceClose(reason); - } - - @Override - public CompletionStage close() { - provider.decrementInUseCount(serverAddress()); - return delegate.close(); - } - - @Override - public CompletionStage setReadTimeout(Duration duration) { - return delegate.setReadTimeout(duration); - } - - @Override - public BoltConnectionState state() { - return delegate.state(); - } - - @Override - public CompletionStage authInfo() { - return delegate.authInfo(); - } - - @Override - public String serverAgent() { - return delegate.serverAgent(); - } - - @Override - public BoltServerAddress serverAddress() { - return delegate.serverAddress(); - } - - @Override - public BoltProtocolVersion protocolVersion() { - return delegate.protocolVersion(); - } - - @Override - public boolean telemetrySupported() { - return delegate.telemetrySupported(); - } - - @Override - public boolean serverSideRoutingEnabled() { - return delegate.serverSideRoutingEnabled(); - } - - @Override - public Optional defaultReadTimeout() { - return delegate.defaultReadTimeout(); - } - - private Throwable handledError(Throwable receivedError, boolean notifyHandler) { - var error = FutureUtil.completionExceptionCause(receivedError); - - if (error instanceof BoltServiceUnavailableException boltServiceUnavailableException) { - return handledServiceUnavailableException(boltServiceUnavailableException, notifyHandler); - } else if (error instanceof BoltFailureException boltFailureException) { - return handledBoltFailureException(boltFailureException, notifyHandler); - } else { - return error; - } - } - - private Throwable handledServiceUnavailableException(BoltServiceUnavailableException e, boolean notifyHandler) { - if (notifyHandler) { - routingTableHandler.onConnectionFailure(serverAddress()); - } - return new BoltServiceUnavailableException(format("Server at %s is no longer available", serverAddress()), e); - } - - private Throwable handledBoltFailureException(BoltFailureException e, boolean notifyHandler) { - var errorCode = e.code(); - if (Objects.equals(errorCode, "Neo.TransientError.General.DatabaseUnavailable")) { - if (notifyHandler) { - routingTableHandler.onConnectionFailure(serverAddress()); - } - } else if (isFailureToWrite(errorCode)) { - // The server is unaware of the session mode, so we have to implement this logic in the driver. - // In the future, we might be able to move this logic to the server. - switch (accessMode) { - case READ -> {} - case WRITE -> { - if (notifyHandler) { - routingTableHandler.onWriteFailure(serverAddress()); - } - } - } - } - return e; - } - - private static boolean isFailureToWrite(String errorCode) { - return Objects.equals(errorCode, "Neo.ClientError.Cluster.NotALeader") - || Objects.equals(errorCode, "Neo.ClientError.General.ForbiddenOnReadOnlyDatabase"); - } -} diff --git a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/ClusterRoutingTable.java b/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/ClusterRoutingTable.java deleted file mode 100644 index afe398b9b9..0000000000 --- a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/ClusterRoutingTable.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl.cluster; - -import static java.lang.String.format; -import static java.util.Arrays.asList; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.LockUtil.executeWithLock; - -import java.time.Clock; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.ClusterComposition; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.routedimpl.RoutingTable; - -public class ClusterRoutingTable implements RoutingTable { - private final ReadWriteLock tableLock = new ReentrantReadWriteLock(); - private final DatabaseName databaseName; - private final Clock clock; - private final Set disused = new HashSet<>(); - - private long expirationTimestamp; - private boolean preferInitialRouter = true; - private List readers = Collections.emptyList(); - private List writers = Collections.emptyList(); - private List routers = Collections.emptyList(); - - public ClusterRoutingTable(DatabaseName ofDatabase, Clock clock, BoltServerAddress... routingAddresses) { - this(ofDatabase, clock); - routers = Collections.unmodifiableList(asList(routingAddresses)); - } - - private ClusterRoutingTable(DatabaseName ofDatabase, Clock clock) { - this.databaseName = ofDatabase; - this.clock = clock; - this.expirationTimestamp = clock.millis() - 1; - } - - @Override - public boolean isStaleFor(AccessMode mode) { - return executeWithLock( - tableLock.readLock(), - () -> expirationTimestamp < clock.millis() - || routers.isEmpty() - || mode == AccessMode.READ && readers.isEmpty() - || mode == AccessMode.WRITE && writers.isEmpty()); - } - - @Override - public boolean hasBeenStaleFor(long extraTime) { - var totalTime = executeWithLock(tableLock.readLock(), () -> expirationTimestamp) + extraTime; - if (totalTime < 0) { - totalTime = Long.MAX_VALUE; - } - return totalTime < clock.millis(); - } - - @Override - public void update(ClusterComposition cluster) { - executeWithLock(tableLock.writeLock(), () -> { - expirationTimestamp = cluster.expirationTimestamp(); - readers = newWithReusedAddresses(readers, disused, cluster.readers()); - writers = newWithReusedAddresses(writers, disused, cluster.writers()); - routers = newWithReusedAddresses(routers, disused, cluster.routers()); - disused.clear(); - preferInitialRouter = !cluster.hasWriters(); - }); - } - - @Override - public void forget(BoltServerAddress address) { - executeWithLock(tableLock.writeLock(), () -> { - routers = newWithoutAddressIfPresent(routers, address); - readers = newWithoutAddressIfPresent(readers, address); - writers = newWithoutAddressIfPresent(writers, address); - disused.add(address); - }); - } - - @Override - public List readers() { - return executeWithLock(tableLock.readLock(), () -> readers); - } - - @Override - public List writers() { - return executeWithLock(tableLock.readLock(), () -> writers); - } - - @Override - public List routers() { - return executeWithLock(tableLock.readLock(), () -> routers); - } - - @Override - public Set servers() { - return executeWithLock(tableLock.readLock(), () -> { - Set servers = new HashSet<>(); - servers.addAll(readers); - servers.addAll(writers); - servers.addAll(routers); - servers.addAll(disused); - return servers; - }); - } - - @Override - public DatabaseName database() { - return databaseName; - } - - @Override - public void forgetWriter(BoltServerAddress toRemove) { - executeWithLock(tableLock.writeLock(), () -> { - writers = newWithoutAddressIfPresent(writers, toRemove); - disused.add(toRemove); - }); - } - - @Override - public void replaceRouterIfPresent(BoltServerAddress oldRouter, BoltServerAddress newRouter) { - executeWithLock( - tableLock.writeLock(), () -> routers = newWithAddressReplacedIfPresent(routers, oldRouter, newRouter)); - } - - @Override - public boolean preferInitialRouter() { - return executeWithLock(tableLock.readLock(), () -> preferInitialRouter); - } - - @Override - public long expirationTimestamp() { - return executeWithLock(tableLock.readLock(), () -> expirationTimestamp); - } - - @Override - public String toString() { - return executeWithLock( - tableLock.readLock(), - () -> format( - "Ttl %s, currentTime %s, routers %s, writers %s, readers %s, database '%s'", - expirationTimestamp, clock.millis(), routers, writers, readers, databaseName.description())); - } - - private List newWithoutAddressIfPresent( - List addresses, BoltServerAddress addressToSkip) { - return addresses.stream() - .filter(address -> !address.equals(addressToSkip)) - .toList(); - } - - private List newWithAddressReplacedIfPresent( - List addresses, BoltServerAddress oldAddress, BoltServerAddress newAddress) { - return addresses.stream() - .map(address -> address.equals(oldAddress) ? newAddress : address) - .toList(); - } - - private List newWithReusedAddresses( - List currentAddresses, - Set disusedAddresses, - Set newAddresses) { - List newList = Stream.concat(currentAddresses.stream(), disusedAddresses.stream()) - .filter(address -> newAddresses.remove(toBoltServerAddress(address))) - .collect(Collectors.toCollection(() -> new ArrayList<>(newAddresses.size()))); - newList.addAll(newAddresses); - return Collections.unmodifiableList(newList); - } - - private BoltServerAddress toBoltServerAddress(BoltServerAddress address) { - return BoltServerAddress.class.equals(address.getClass()) - ? address - : new BoltServerAddress(address.host(), address.port()); - } -} diff --git a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RediscoveryImpl.java b/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RediscoveryImpl.java deleted file mode 100644 index 7ae0969444..0000000000 --- a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RediscoveryImpl.java +++ /dev/null @@ -1,585 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl.cluster; - -import static java.lang.String.format; -import static java.util.Collections.emptySet; -import static java.util.Objects.requireNonNull; -import static java.util.concurrent.CompletableFuture.completedFuture; - -import java.net.UnknownHostException; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Function; -import java.util.function.Supplier; -import javax.net.ssl.SSLHandshakeException; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.AuthToken; -import org.neo4j.driver.internal.bolt.api.BoltAgent; -import org.neo4j.driver.internal.bolt.api.BoltConnection; -import org.neo4j.driver.internal.bolt.api.BoltConnectionProvider; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.ClusterComposition; -import org.neo4j.driver.internal.bolt.api.DomainNameResolver; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.ResponseHandler; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; -import org.neo4j.driver.internal.bolt.api.exception.BoltDiscoveryException; -import org.neo4j.driver.internal.bolt.api.exception.BoltFailureException; -import org.neo4j.driver.internal.bolt.api.exception.BoltProtocolException; -import org.neo4j.driver.internal.bolt.api.exception.BoltServiceUnavailableException; -import org.neo4j.driver.internal.bolt.api.exception.BoltUnsupportedFeatureException; -import org.neo4j.driver.internal.bolt.api.exception.MinVersionAcquisitionException; -import org.neo4j.driver.internal.bolt.api.summary.RouteSummary; -import org.neo4j.driver.internal.bolt.routedimpl.ClusterCompositionLookupResult; -import org.neo4j.driver.internal.bolt.routedimpl.Rediscovery; -import org.neo4j.driver.internal.bolt.routedimpl.RoutingTable; -import org.neo4j.driver.internal.bolt.routedimpl.impl.AuthTokenManagerExecutionException; -import org.neo4j.driver.internal.bolt.routedimpl.impl.util.FutureUtil; - -public class RediscoveryImpl implements Rediscovery { - private static final String NO_ROUTERS_AVAILABLE = - "Could not perform discovery for database '%s'. No routing server available."; - private static final String RECOVERABLE_ROUTING_ERROR = "Failed to update routing table with server '%s'."; - private static final String RECOVERABLE_DISCOVERY_ERROR_WITH_SERVER = - "Received a recoverable discovery error with server '%s', " - + "will continue discovery with other routing servers if available. " - + "Complete failure is reported separately from this entry."; - private static final String TRANSACTION_INVALID_BOOKMARK_CODE = "Neo.ClientError.Transaction.InvalidBookmark"; - private static final String TRANSACTION_INVALID_BOOKMARK_MIXTURE_CODE = - "Neo.ClientError.Transaction.InvalidBookmarkMixture"; - private static final String STATEMENT_ARGUMENT_ERROR_CODE = "Neo.ClientError.Statement.ArgumentError"; - private static final String REQUEST_INVALID_CODE = "Neo.ClientError.Request.Invalid"; - private static final String STATEMENT_TYPE_ERROR_CODE = "Neo.ClientError.Statement.TypeError"; - - private final BoltServerAddress initialRouter; - private final System.Logger log; - private final Function> resolver; - private final DomainNameResolver domainNameResolver; - private final RoutingContext routingContext; - private final BoltAgent boltAgent; - private final String userAgent; - private final int connectTimeoutMillis; - - public RediscoveryImpl( - BoltServerAddress initialRouter, - Function> resolver, - LoggingProvider logging, - DomainNameResolver domainNameResolver, - RoutingContext routingContext, - BoltAgent boltAgent, - String userAgent, - int connectTimeoutMillis) { - this.initialRouter = initialRouter; - this.log = logging.getLog(getClass()); - this.resolver = resolver; - this.domainNameResolver = requireNonNull(domainNameResolver); - this.routingContext = routingContext; - this.boltAgent = boltAgent; - this.userAgent = userAgent; - this.connectTimeoutMillis = connectTimeoutMillis; - } - - @Override - public CompletionStage lookupClusterComposition( - SecurityPlan securityPlan, - RoutingTable routingTable, - Function connectionProviderGetter, - Set bookmarks, - String impersonatedUser, - Supplier> authTokenStageSupplier, - BoltProtocolVersion minVersion) { - var result = new CompletableFuture(); - // if we failed discovery, we will chain all errors into this one. - var baseError = new BoltServiceUnavailableException( - String.format(NO_ROUTERS_AVAILABLE, routingTable.database().description())); - lookupClusterComposition( - securityPlan, - routingTable, - connectionProviderGetter, - result, - bookmarks, - impersonatedUser, - authTokenStageSupplier, - minVersion, - baseError); - return result; - } - - private void lookupClusterComposition( - SecurityPlan securityPlan, - RoutingTable routingTable, - Function connectionProviderGetter, - CompletableFuture result, - Set bookmarks, - String impersonatedUser, - Supplier> authTokenStageSupplier, - BoltProtocolVersion minVersion, - Throwable baseError) { - lookup( - securityPlan, - routingTable, - connectionProviderGetter, - bookmarks, - impersonatedUser, - authTokenStageSupplier, - minVersion, - baseError) - .whenComplete((compositionLookupResult, completionError) -> { - var error = FutureUtil.completionExceptionCause(completionError); - if (error != null) { - result.completeExceptionally(error); - } else if (compositionLookupResult != null) { - result.complete(compositionLookupResult); - } else { - result.completeExceptionally(baseError); - } - }); - } - - private CompletionStage lookup( - SecurityPlan securityPlan, - RoutingTable routingTable, - Function connectionProviderGetter, - Set bookmarks, - String impersonatedUser, - Supplier> authTokenStageSupplier, - BoltProtocolVersion minVersion, - Throwable baseError) { - CompletionStage compositionStage; - - if (routingTable.preferInitialRouter()) { - compositionStage = lookupOnInitialRouterThenOnKnownRouters( - securityPlan, - routingTable, - connectionProviderGetter, - bookmarks, - impersonatedUser, - authTokenStageSupplier, - minVersion, - baseError); - } else { - compositionStage = lookupOnKnownRoutersThenOnInitialRouter( - securityPlan, - routingTable, - connectionProviderGetter, - bookmarks, - impersonatedUser, - authTokenStageSupplier, - minVersion, - baseError); - } - - return compositionStage; - } - - private CompletionStage lookupOnKnownRoutersThenOnInitialRouter( - SecurityPlan securityPlan, - RoutingTable routingTable, - Function connectionProviderGetter, - Set bookmarks, - String impersonatedUser, - Supplier> authTokenStageSupplier, - BoltProtocolVersion minVersion, - Throwable baseError) { - Set seenServers = new HashSet<>(); - return lookupOnKnownRouters( - securityPlan, - routingTable, - connectionProviderGetter, - seenServers, - bookmarks, - impersonatedUser, - authTokenStageSupplier, - minVersion, - baseError) - .thenCompose(compositionLookupResult -> { - if (compositionLookupResult != null) { - return completedFuture(compositionLookupResult); - } - return lookupOnInitialRouter( - securityPlan, - routingTable, - connectionProviderGetter, - seenServers, - bookmarks, - impersonatedUser, - authTokenStageSupplier, - minVersion, - baseError); - }); - } - - private CompletionStage lookupOnInitialRouterThenOnKnownRouters( - SecurityPlan securityPlan, - RoutingTable routingTable, - Function connectionProviderGetter, - Set bookmarks, - String impersonatedUser, - Supplier> authTokenStageSupplier, - BoltProtocolVersion minVersion, - Throwable baseError) { - Set seenServers = emptySet(); - return lookupOnInitialRouter( - securityPlan, - routingTable, - connectionProviderGetter, - seenServers, - bookmarks, - impersonatedUser, - authTokenStageSupplier, - minVersion, - baseError) - .thenCompose(compositionLookupResult -> { - if (compositionLookupResult != null) { - return completedFuture(compositionLookupResult); - } - return lookupOnKnownRouters( - securityPlan, - routingTable, - connectionProviderGetter, - new HashSet<>(), - bookmarks, - impersonatedUser, - authTokenStageSupplier, - minVersion, - baseError); - }); - } - - private CompletionStage lookupOnKnownRouters( - SecurityPlan securityPlan, - RoutingTable routingTable, - Function connectionProviderGetter, - Set seenServers, - Set bookmarks, - String impersonatedUser, - Supplier> authTokenStageSupplier, - BoltProtocolVersion minVersion, - Throwable baseError) { - CompletableFuture result = CompletableFuture.completedFuture(null); - for (var address : routingTable.routers()) { - result = result.thenCompose(composition -> { - if (composition != null) { - return completedFuture(composition); - } else { - return lookupOnRouter( - securityPlan, - address, - true, - routingTable, - connectionProviderGetter, - seenServers, - bookmarks, - impersonatedUser, - authTokenStageSupplier, - minVersion, - baseError); - } - }); - } - return result.thenApply( - composition -> composition != null ? new ClusterCompositionLookupResult(composition) : null); - } - - private CompletionStage lookupOnInitialRouter( - SecurityPlan securityPlan, - RoutingTable routingTable, - Function connectionProviderGetter, - Set seenServers, - Set bookmarks, - String impersonatedUser, - Supplier> authTokenStageSupplier, - BoltProtocolVersion minVersion, - Throwable baseError) { - List resolvedRouters; - try { - resolvedRouters = resolve(); - } catch (Throwable error) { - return CompletableFuture.failedFuture(error); - } - Set resolvedRouterSet = new HashSet<>(resolvedRouters); - resolvedRouters.removeAll(seenServers); - - CompletableFuture result = CompletableFuture.completedFuture(null); - for (var address : resolvedRouters) { - result = result.thenCompose(composition -> { - if (composition != null) { - return completedFuture(composition); - } - return lookupOnRouter( - securityPlan, - address, - false, - routingTable, - connectionProviderGetter, - null, - bookmarks, - impersonatedUser, - authTokenStageSupplier, - minVersion, - baseError); - }); - } - return result.thenApply(composition -> - composition != null ? new ClusterCompositionLookupResult(composition, resolvedRouterSet) : null); - } - - private CompletionStage lookupOnRouter( - SecurityPlan securityPlan, - BoltServerAddress routerAddress, - boolean resolveAddress, - RoutingTable routingTable, - Function connectionProviderGetter, - Set seenServers, - Set bookmarks, - String impersonatedUser, - Supplier> authTokenStageSupplier, - BoltProtocolVersion minVersion, - Throwable baseError) { - var addressFuture = CompletableFuture.completedFuture(routerAddress); - - var future = new CompletableFuture(); - var compositionFuture = new CompletableFuture(); - var connectionRef = new AtomicReference(); - - addressFuture - .thenApply(address -> - resolveAddress ? resolveByDomainNameOrThrowCompletionException(address, routingTable) : address) - .thenApply(address -> addAndReturn(seenServers, address)) - .thenCompose(address -> connectionProviderGetter - .apply(address) - .connect( - address, - routingContext, - boltAgent, - userAgent, - connectTimeoutMillis, - securityPlan, - null, - authTokenStageSupplier, - AccessMode.READ, - bookmarks, - null, - minVersion, - null, - (ignored) -> {}, - Collections.emptyMap())) - .thenApply(connection -> { - connectionRef.set(connection); - return connection; - }) - .thenCompose(connection -> connection.route(routingTable.database(), impersonatedUser, bookmarks)) - .thenCompose(connection -> connection.flush(new ResponseHandler() { - ClusterComposition clusterComposition; - Throwable throwable; - - @Override - public void onError(Throwable throwable) { - this.throwable = throwable; - } - - @Override - public void onRouteSummary(RouteSummary summary) { - clusterComposition = summary.clusterComposition(); - } - - @Override - public void onComplete() { - if (throwable != null) { - compositionFuture.completeExceptionally(throwable); - } else { - compositionFuture.complete(clusterComposition); - } - } - })) - .thenCompose(ignored -> compositionFuture) - .thenApply(clusterComposition -> { - if (clusterComposition.routers().isEmpty() - || clusterComposition.readers().isEmpty()) { - throw new CompletionException( - new BoltProtocolException( - "Failed to parse result received from server due to no router or reader found in response.")); - } else { - return clusterComposition; - } - }) - .whenComplete((clusterComposition, throwable) -> { - var connection = connectionRef.get(); - var connectionCloseStage = - connection != null ? connection.close() : CompletableFuture.completedStage(null); - var cause = FutureUtil.completionExceptionCause(throwable); - if (cause != null) { - connectionCloseStage.whenComplete((ignored1, ignored2) -> { - try { - var composition = handleRoutingProcedureError( - FutureUtil.completionExceptionCause(throwable), - routingTable, - routerAddress, - baseError); - future.complete(composition); - } catch (Throwable abortError) { - future.completeExceptionally(abortError); - } - }); - } else { - connectionCloseStage.whenComplete((ignored1, ignored2) -> future.complete(clusterComposition)); - } - }); - - return future; - } - - @SuppressWarnings({"ThrowableNotThrown", "SameReturnValue"}) - private ClusterComposition handleRoutingProcedureError( - Throwable error, RoutingTable routingTable, BoltServerAddress routerAddress, Throwable baseError) { - if (mustAbortDiscovery(error)) { - throw new CompletionException(error); - } - - // Retryable error happened during discovery. - var discoveryError = new BoltDiscoveryException(format(RECOVERABLE_ROUTING_ERROR, routerAddress), error); - FutureUtil.combineErrors(baseError, discoveryError); // we record each failure here - log.log(System.Logger.Level.WARNING, RECOVERABLE_DISCOVERY_ERROR_WITH_SERVER, routerAddress); - log.log( - System.Logger.Level.DEBUG, - format(RECOVERABLE_DISCOVERY_ERROR_WITH_SERVER, routerAddress), - discoveryError); - routingTable.forget(routerAddress); - return null; - } - - @SuppressWarnings("SwitchStatementWithTooFewBranches") - private boolean mustAbortDiscovery(Throwable throwable) { - var abort = false; - - if (throwable instanceof BoltFailureException boltFailureException) { - var code = boltFailureException.code(); - abort = switch (extractErrorClass(code)) { - case "ClientError" -> { - if ("Security".equals(extractErrorSubClass(code))) { - yield !"Neo.ClientError.Security.AuthorizationExpired".equalsIgnoreCase(code); - } else { - if ("Neo.ClientError.Database.DatabaseNotFound".equalsIgnoreCase(code)) { - yield true; - } else { - yield switch (code) { - case TRANSACTION_INVALID_BOOKMARK_CODE, - TRANSACTION_INVALID_BOOKMARK_MIXTURE_CODE, - STATEMENT_ARGUMENT_ERROR_CODE, - REQUEST_INVALID_CODE, - STATEMENT_TYPE_ERROR_CODE -> true; - default -> false; - }; - } - } - } - default -> false;}; - } else if (throwable instanceof IllegalStateException - && "Connection provider is closed.".equals(throwable.getMessage())) { - abort = true; - } else if (throwable instanceof BoltUnsupportedFeatureException) { - abort = true; - } else if (throwable instanceof MinVersionAcquisitionException) { - abort = true; - } else if (throwable instanceof SSLHandshakeException) { - abort = true; - } else if (throwable instanceof AuthTokenManagerExecutionException) { - abort = true; - } - - return abort; - } - - private static String extractErrorClass(String code) { - var parts = code.split("\\."); - if (parts.length < 2) { - return ""; - } - return parts[1]; - } - - private static String extractErrorSubClass(String code) { - var parts = code.split("\\."); - if (parts.length < 3) { - return ""; - } - return parts[2]; - } - - @Override - public List resolve() throws UnknownHostException { - List resolvedAddresses = new LinkedList<>(); - UnknownHostException exception = null; - for (var serverAddress : resolver.apply(initialRouter)) { - try { - resolveAllByDomainName(serverAddress).unicastStream().forEach(resolvedAddresses::add); - } catch (UnknownHostException e) { - if (exception == null) { - exception = e; - } else { - exception.addSuppressed(e); - } - } - } - - // give up only if there are no addresses to work with at all - if (resolvedAddresses.isEmpty() && exception != null) { - throw exception; - } - - return resolvedAddresses; - } - - private T addAndReturn(Collection collection, T element) { - if (collection != null) { - collection.add(element); - } - return element; - } - - private BoltServerAddress resolveByDomainNameOrThrowCompletionException( - BoltServerAddress address, RoutingTable routingTable) { - try { - var resolvedAddress = resolveAllByDomainName(address); - routingTable.replaceRouterIfPresent(address, resolvedAddress); - return resolvedAddress - .unicastStream() - .findFirst() - .orElseThrow( - () -> new IllegalStateException( - "Unexpected condition, the ResolvedBoltServerAddress must always have at least one unicast address")); - } catch (Throwable e) { - throw new CompletionException(e); - } - } - - private ResolvedBoltServerAddress resolveAllByDomainName(BoltServerAddress address) throws UnknownHostException { - return new ResolvedBoltServerAddress( - address.host(), address.port(), domainNameResolver.resolve(address.host())); - } -} diff --git a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/ResolvedBoltServerAddress.java b/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/ResolvedBoltServerAddress.java deleted file mode 100644 index edb7533cb7..0000000000 --- a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/ResolvedBoltServerAddress.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl.cluster; - -import static java.util.Objects.requireNonNull; -import static java.util.stream.Collectors.joining; - -import java.net.InetAddress; -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Stream; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; - -/** - * An explicitly resolved version of {@link BoltServerAddress} that always contains one or more resolved IP addresses. - */ -class ResolvedBoltServerAddress extends BoltServerAddress { - private static final String HOST_ADDRESSES_FORMAT = "%s%s:%d"; - private static final int MAX_HOST_ADDRESSES_IN_STRING_VALUE = 5; - private static final String HOST_ADDRESS_DELIMITER = ","; - private static final String HOST_ADDRESSES_PREFIX = "("; - private static final String HOST_ADDRESSES_SUFFIX = ")"; - private static final String TRIMMED_HOST_ADDRESSES_SUFFIX = ",..." + HOST_ADDRESSES_SUFFIX; - - private final Set resolvedAddresses; - private final String stringValue; - - public ResolvedBoltServerAddress(String host, int port, InetAddress[] resolvedAddressesArr) { - super(host, port); - requireNonNull(resolvedAddressesArr, "resolvedAddressesArr"); - if (resolvedAddressesArr.length == 0) { - throw new IllegalArgumentException( - "The resolvedAddressesArr must not be empty, check your DomainNameResolver is compliant with the interface contract"); - } - resolvedAddresses = Collections.unmodifiableSet(new LinkedHashSet<>(Arrays.asList(resolvedAddressesArr))); - stringValue = createStringRepresentation(); - } - - /** - * Create a stream of unicast addresses. - *

- * The stream is created from the list of resolved IP addresses. Each unicast address is given a unique IP address as the connectionHost value. - * - * @return stream of unicast addresses. - */ - @Override - public Stream unicastStream() { - return resolvedAddresses.stream().map(address -> new BoltServerAddress(host, address.getHostAddress(), port)); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - if (!super.equals(o)) { - return false; - } - var that = (ResolvedBoltServerAddress) o; - return resolvedAddresses.equals(that.resolvedAddresses); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), resolvedAddresses); - } - - @Override - public String toString() { - return stringValue; - } - - private String createStringRepresentation() { - var hostAddresses = resolvedAddresses.stream() - .limit(MAX_HOST_ADDRESSES_IN_STRING_VALUE) - .map(InetAddress::getHostAddress) - .collect(joining( - HOST_ADDRESS_DELIMITER, - HOST_ADDRESSES_PREFIX, - resolvedAddresses.size() > MAX_HOST_ADDRESSES_IN_STRING_VALUE - ? TRIMMED_HOST_ADDRESSES_SUFFIX - : HOST_ADDRESSES_SUFFIX)); - return String.format(HOST_ADDRESSES_FORMAT, host, hostAddresses, port); - } -} diff --git a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RoutingErrorHandler.java b/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RoutingErrorHandler.java deleted file mode 100644 index f90c8c64c9..0000000000 --- a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RoutingErrorHandler.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl.cluster; - -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; - -/** - * Interface used for tracking errors when connected to a cluster. - */ -interface RoutingErrorHandler { - void onConnectionFailure(BoltServerAddress address); - - void onWriteFailure(BoltServerAddress address); -} diff --git a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RoutingTableHandler.java b/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RoutingTableHandler.java deleted file mode 100644 index 7445dbc43a..0000000000 --- a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RoutingTableHandler.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl.cluster; - -import java.util.Set; -import java.util.concurrent.CompletionStage; -import java.util.function.Supplier; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.AuthToken; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; -import org.neo4j.driver.internal.bolt.routedimpl.ClusterCompositionLookupResult; -import org.neo4j.driver.internal.bolt.routedimpl.RoutingTable; - -public interface RoutingTableHandler extends RoutingErrorHandler { - Set servers(); - - boolean isRoutingTableAged(); - - CompletionStage ensureRoutingTable( - SecurityPlan securityPlan, - AccessMode mode, - Set rediscoveryBookmarks, - Supplier> authTokenStageSupplier, - BoltProtocolVersion minVersion); - - CompletionStage updateRoutingTable(ClusterCompositionLookupResult compositionLookupResult); - - RoutingTable routingTable(); - - boolean isStaleFor(AccessMode mode); -} diff --git a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RoutingTableHandlerImpl.java b/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RoutingTableHandlerImpl.java deleted file mode 100644 index ee3303fdf8..0000000000 --- a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RoutingTableHandlerImpl.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl.cluster; - -import static java.util.concurrent.CompletableFuture.completedFuture; - -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.AuthToken; -import org.neo4j.driver.internal.bolt.api.BoltConnectionProvider; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; -import org.neo4j.driver.internal.bolt.routedimpl.ClusterCompositionLookupResult; -import org.neo4j.driver.internal.bolt.routedimpl.Rediscovery; -import org.neo4j.driver.internal.bolt.routedimpl.RoutingTable; -import org.neo4j.driver.internal.bolt.routedimpl.impl.util.FutureUtil; - -public class RoutingTableHandlerImpl implements RoutingTableHandler { - private final RoutingTable routingTable; - private final DatabaseName databaseName; - private final RoutingTableRegistry routingTableRegistry; - private volatile CompletableFuture refreshRoutingTableFuture; - private final Function connectionProviderGetter; - private final Rediscovery rediscovery; - private final System.Logger log; - private final long routingTablePurgeDelayMs; - private final Set resolvedInitialRouters = new HashSet<>(); - private final Consumer> addressesToRetainConsumer; - - public RoutingTableHandlerImpl( - RoutingTable routingTable, - Rediscovery rediscovery, - Function connectionProviderGetter, - RoutingTableRegistry routingTableRegistry, - LoggingProvider logging, - long routingTablePurgeDelayMs, - Consumer> addressesToRetainConsumer) { - this.routingTable = routingTable; - this.databaseName = routingTable.database(); - this.rediscovery = rediscovery; - this.connectionProviderGetter = connectionProviderGetter; - this.routingTableRegistry = routingTableRegistry; - this.log = logging.getLog(getClass()); - this.routingTablePurgeDelayMs = routingTablePurgeDelayMs; - this.addressesToRetainConsumer = addressesToRetainConsumer; - } - - @Override - public void onConnectionFailure(BoltServerAddress address) { - // remove server from the routing table, to prevent concurrent threads from making connections to this address - routingTable.forget(address); - } - - @Override - public void onWriteFailure(BoltServerAddress address) { - routingTable.forgetWriter(address); - } - - @Override - public synchronized CompletionStage ensureRoutingTable( - SecurityPlan securityPlan, - AccessMode mode, - Set rediscoveryBookmarks, - Supplier> authTokenStageSupplier, - BoltProtocolVersion minVersion) { - if (refreshRoutingTableFuture != null) { - // refresh is already happening concurrently, just use it's result - return refreshRoutingTableFuture; - } else if (routingTable.isStaleFor(mode)) { - // existing routing table is not fresh and should be updated - log.log( - System.Logger.Level.DEBUG, - "Routing table for database '%s' is stale. %s", - databaseName.description(), - routingTable); - - var resultFuture = new CompletableFuture(); - refreshRoutingTableFuture = resultFuture; - - rediscovery - .lookupClusterComposition( - securityPlan, - routingTable, - connectionProviderGetter, - rediscoveryBookmarks, - null, - authTokenStageSupplier, - minVersion) - .whenComplete((composition, completionError) -> { - var error = FutureUtil.completionExceptionCause(completionError); - if (error != null) { - clusterCompositionLookupFailed(error); - } else { - freshClusterCompositionFetched(composition); - } - }); - - return resultFuture; - } else { - // existing routing table is fresh, use it - return completedFuture(routingTable); - } - } - - @Override - public synchronized CompletionStage updateRoutingTable( - ClusterCompositionLookupResult compositionLookupResult) { - if (refreshRoutingTableFuture != null) { - // refresh is already happening concurrently, just use its result - return refreshRoutingTableFuture; - } else { - if (compositionLookupResult.getClusterComposition().expirationTimestamp() - < routingTable.expirationTimestamp()) { - return completedFuture(routingTable); - } - var resultFuture = new CompletableFuture(); - refreshRoutingTableFuture = resultFuture; - freshClusterCompositionFetched(compositionLookupResult); - return resultFuture; - } - } - - private synchronized void freshClusterCompositionFetched(ClusterCompositionLookupResult compositionLookupResult) { - try { - log.log( - System.Logger.Level.DEBUG, - "Fetched cluster composition for database '%s'. %s", - databaseName.description(), - compositionLookupResult.getClusterComposition()); - routingTable.update(compositionLookupResult.getClusterComposition()); - routingTableRegistry.removeAged(); - - Set addressesToRetain = new LinkedHashSet<>(); - routingTableRegistry.allServers().stream() - .flatMap(BoltServerAddress::unicastStream) - .forEach(addressesToRetain::add); - compositionLookupResult.getResolvedInitialRouters().ifPresent(addresses -> { - resolvedInitialRouters.clear(); - resolvedInitialRouters.addAll(addresses); - }); - addressesToRetain.addAll(resolvedInitialRouters); - addressesToRetainConsumer.accept(addressesToRetain); - - log.log( - System.Logger.Level.DEBUG, - "Updated routing table for database '%s'. %s", - databaseName.description(), - routingTable); - - var routingTableFuture = refreshRoutingTableFuture; - refreshRoutingTableFuture = null; - routingTableFuture.complete(routingTable); - } catch (Throwable error) { - clusterCompositionLookupFailed(error); - } - } - - private synchronized void clusterCompositionLookupFailed(Throwable error) { - log.log( - System.Logger.Level.ERROR, - String.format( - "Failed to update routing table for database '%s'. Current routing table: %s.", - databaseName.description(), routingTable), - error); - routingTableRegistry.remove(databaseName); - var routingTableFuture = refreshRoutingTableFuture; - refreshRoutingTableFuture = null; - routingTableFuture.completeExceptionally(error); - } - - // This method cannot be synchronized as it will be visited by all routing table handler's threads concurrently - @Override - public Set servers() { - return routingTable.servers(); - } - - // This method cannot be synchronized as it will be visited by all routing table handler's threads concurrently - @Override - public boolean isRoutingTableAged() { - return refreshRoutingTableFuture == null && routingTable.hasBeenStaleFor(routingTablePurgeDelayMs); - } - - public RoutingTable routingTable() { - return routingTable; - } - - @Override - public synchronized boolean isStaleFor(AccessMode mode) { - if (refreshRoutingTableFuture != null) { - return true; - } - return routingTable.isStaleFor(mode); - } -} diff --git a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RoutingTableRegistry.java b/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RoutingTableRegistry.java deleted file mode 100644 index 2d6d4ea044..0000000000 --- a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RoutingTableRegistry.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl.cluster; - -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import java.util.function.Supplier; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.AuthToken; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; - -/** - * A generic interface to access all routing tables as a whole. - * It also provides methods to obtain a routing table or manage a routing table for a specified database. - */ -public interface RoutingTableRegistry { - /** - * Ensures the routing table for the database with given access mode. - * For server version lower than 4.0, the database name will be ignored while refreshing routing table. - * @return The future of a new routing table handler. - */ - CompletionStage ensureRoutingTable( - SecurityPlan securityPlan, - CompletableFuture databaseNameFuture, - AccessMode mode, - Set rediscoveryBookmarks, - String impersonatedUser, - Supplier> authTokenStageSupplier, - BoltProtocolVersion minVersion, - String homeDatabaseHint); - - /** - * @return all servers in the registry - */ - Set allServers(); - - /** - * Removes a routing table of the given database from registry. - */ - void remove(DatabaseName databaseName); - - /** - * Removes all routing tables that has been not used for a long time. - */ - void removeAged(); - - /** - * Returns routing table handler for the given database name if it exists in the registry. - * - * @param databaseName the database name - * @return the routing table handler for the requested database name - */ - Optional getRoutingTableHandler(DatabaseName databaseName); -} diff --git a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RoutingTableRegistryImpl.java b/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RoutingTableRegistryImpl.java deleted file mode 100644 index 8509890ab9..0000000000 --- a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RoutingTableRegistryImpl.java +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl.cluster; - -import static java.util.Objects.requireNonNull; - -import java.time.Clock; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Collectors; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.AuthToken; -import org.neo4j.driver.internal.bolt.api.BoltConnectionProvider; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.DatabaseNameUtil; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; -import org.neo4j.driver.internal.bolt.routedimpl.Rediscovery; -import org.neo4j.driver.internal.bolt.routedimpl.impl.util.FutureUtil; - -public class RoutingTableRegistryImpl implements RoutingTableRegistry { - private static final Supplier PENDING_DATABASE_NAME_EXCEPTION_SUPPLIER = - () -> new IllegalStateException("Pending database name encountered."); - private final ConcurrentMap routingTableHandlers; - private final Map> principalToDatabaseNameStage; - private final RoutingTableHandlerFactory factory; - private final System.Logger log; - private final Clock clock; - private final Function connectionProviderGetter; - private final Rediscovery rediscovery; - - public RoutingTableRegistryImpl( - Function connectionProviderGetter, - Rediscovery rediscovery, - Clock clock, - LoggingProvider logging, - long routingTablePurgeDelayMs, - Consumer> addressesToRetainConsumer) { - this( - new ConcurrentHashMap<>(), - new RoutingTableHandlerFactory( - connectionProviderGetter, - rediscovery, - clock, - logging, - routingTablePurgeDelayMs, - addressesToRetainConsumer), - clock, - connectionProviderGetter, - rediscovery, - logging); - } - - RoutingTableRegistryImpl( - ConcurrentMap routingTableHandlers, - RoutingTableHandlerFactory factory, - Clock clock, - Function connectionProviderGetter, - Rediscovery rediscovery, - LoggingProvider logging) { - requireNonNull(rediscovery, "rediscovery must not be null"); - this.factory = factory; - this.routingTableHandlers = routingTableHandlers; - this.principalToDatabaseNameStage = new HashMap<>(); - this.clock = clock; - this.connectionProviderGetter = connectionProviderGetter; - this.rediscovery = rediscovery; - this.log = logging.getLog(getClass()); - } - - @Override - public CompletionStage ensureRoutingTable( - SecurityPlan securityPlan, - CompletableFuture databaseNameFuture, - AccessMode mode, - Set rediscoveryBookmarks, - String impersonatedUser, - Supplier> authTokenStageSupplier, - BoltProtocolVersion minVersion, - String homeDatabaseHint) { - if (!databaseNameFuture.isDone()) { - if (homeDatabaseHint != null) { - var handler = routingTableHandlers.get(DatabaseNameUtil.database(homeDatabaseHint)); - if (handler != null && !handler.isStaleFor(mode)) { - return CompletableFuture.completedFuture(handler); - } - } - } - return ensureDatabaseNameIsCompleted( - securityPlan, - databaseNameFuture, - mode, - rediscoveryBookmarks, - impersonatedUser, - authTokenStageSupplier, - minVersion) - .thenCompose(ctxAndHandler -> { - var handler = ctxAndHandler.handler() != null - ? ctxAndHandler.handler() - : getOrCreate(FutureUtil.joinNowOrElseThrow( - ctxAndHandler.databaseNameFuture(), PENDING_DATABASE_NAME_EXCEPTION_SUPPLIER)); - return handler.ensureRoutingTable( - securityPlan, mode, rediscoveryBookmarks, authTokenStageSupplier, minVersion) - .thenApply(ignored -> handler); - }); - } - - private CompletionStage ensureDatabaseNameIsCompleted( - SecurityPlan securityPlan, - CompletableFuture databaseNameFutureS, - AccessMode mode, - Set rediscoveryBookmarks, - String impersonatedUser, - Supplier> authTokenStageSupplier, - BoltProtocolVersion minVersion) { - CompletionStage contextAndHandlerStage; - - if (databaseNameFutureS.isDone()) { - contextAndHandlerStage = CompletableFuture.completedFuture( - new ConnectionContextAndHandler(databaseNameFutureS, mode, rediscoveryBookmarks, null)); - } else { - synchronized (this) { - if (databaseNameFutureS.isDone()) { - contextAndHandlerStage = CompletableFuture.completedFuture( - new ConnectionContextAndHandler(databaseNameFutureS, mode, rediscoveryBookmarks, null)); - } else { - var principal = new Principal(impersonatedUser); - var databaseNameStage = principalToDatabaseNameStage.get(principal); - var handlerRef = new AtomicReference(); - - if (databaseNameStage == null) { - var databaseNameFuture = new CompletableFuture(); - principalToDatabaseNameStage.put(principal, databaseNameFuture); - databaseNameStage = databaseNameFuture; - - var routingTable = new ClusterRoutingTable(DatabaseNameUtil.defaultDatabase(), clock); - rediscovery - .lookupClusterComposition( - securityPlan, - routingTable, - connectionProviderGetter, - rediscoveryBookmarks, - impersonatedUser, - authTokenStageSupplier, - minVersion) - .thenCompose(compositionLookupResult -> { - var databaseName = DatabaseNameUtil.database(compositionLookupResult - .getClusterComposition() - .databaseName()); - var handler = getOrCreate(databaseName); - handlerRef.set(handler); - return handler.updateRoutingTable(compositionLookupResult) - .thenApply(ignored -> databaseName); - }) - .whenComplete((databaseName, throwable) -> { - synchronized (this) { - principalToDatabaseNameStage.remove(principal); - } - }) - .whenComplete((databaseName, throwable) -> { - if (throwable != null) { - databaseNameFuture.completeExceptionally(throwable); - } else { - databaseNameFuture.complete(databaseName); - } - }); - } - - contextAndHandlerStage = databaseNameStage.thenApply(databaseName -> { - synchronized (this) { - databaseNameFutureS.complete(databaseName); - } - return new ConnectionContextAndHandler( - databaseNameFutureS, mode, rediscoveryBookmarks, handlerRef.get()); - }); - } - } - } - - return contextAndHandlerStage; - } - - @Override - public Set allServers() { - // obviously we just had a snapshot of all servers in all routing tables - // after we read it, the set could already be changed. - return routingTableHandlers.values().stream() - .flatMap(tableHandler -> tableHandler.servers().stream()) - .collect(Collectors.toSet()); - } - - @Override - public void remove(DatabaseName databaseName) { - routingTableHandlers.remove(databaseName); - log.log( - System.Logger.Level.DEBUG, - "Routing table handler for database '%s' is removed.", - databaseName.description()); - } - - @Override - public void removeAged() { - routingTableHandlers.forEach((databaseName, handler) -> { - if (handler.isRoutingTableAged()) { - log.log( - System.Logger.Level.INFO, - "Routing table handler for database '%s' is removed because it has not been used for a long time. Routing table: %s", - databaseName.description(), - handler.routingTable()); - routingTableHandlers.remove(databaseName); - } - }); - } - - @Override - public Optional getRoutingTableHandler(DatabaseName databaseName) { - return Optional.ofNullable(routingTableHandlers.get(databaseName)); - } - - // For tests - public boolean contains(DatabaseName databaseName) { - return routingTableHandlers.containsKey(databaseName); - } - - private RoutingTableHandler getOrCreate(DatabaseName databaseName) { - return routingTableHandlers.computeIfAbsent(databaseName, name -> { - var handler = factory.newInstance(name, this); - log.log( - System.Logger.Level.DEBUG, - "Routing table handler for database '%s' is added.", - databaseName.description()); - return handler; - }); - } - - static class RoutingTableHandlerFactory { - private final Function connectionProviderGetter; - private final Rediscovery rediscovery; - private final LoggingProvider logging; - private final Clock clock; - private final long routingTablePurgeDelayMs; - private final Consumer> addressesToRetainConsumer; - - RoutingTableHandlerFactory( - Function connectionProviderGetter, - Rediscovery rediscovery, - Clock clock, - LoggingProvider logging, - long routingTablePurgeDelayMs, - Consumer> addressesToRetainConsumer) { - this.connectionProviderGetter = connectionProviderGetter; - this.rediscovery = rediscovery; - this.clock = clock; - this.logging = logging; - this.routingTablePurgeDelayMs = routingTablePurgeDelayMs; - this.addressesToRetainConsumer = addressesToRetainConsumer; - } - - RoutingTableHandler newInstance(DatabaseName databaseName, RoutingTableRegistry allTables) { - var routingTable = new ClusterRoutingTable(databaseName, clock); - return new RoutingTableHandlerImpl( - routingTable, - rediscovery, - connectionProviderGetter, - allTables, - logging, - routingTablePurgeDelayMs, - addressesToRetainConsumer); - } - } - - private record Principal(String id) { - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - var principal = (Principal) o; - return Objects.equals(id, principal.id); - } - } - - private record ConnectionContextAndHandler( - CompletableFuture databaseNameFuture, - AccessMode mode, - Set rediscoveryBookmarks, - RoutingTableHandler handler) {} -} diff --git a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/loadbalancing/LeastConnectedLoadBalancingStrategy.java b/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/loadbalancing/LeastConnectedLoadBalancingStrategy.java deleted file mode 100644 index ae21fefe75..0000000000 --- a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/loadbalancing/LeastConnectedLoadBalancingStrategy.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl.cluster.loadbalancing; - -import java.util.List; -import java.util.function.Function; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; - -public class LeastConnectedLoadBalancingStrategy implements LoadBalancingStrategy { - private final RoundRobinArrayIndex readersIndex = new RoundRobinArrayIndex(); - private final RoundRobinArrayIndex writersIndex = new RoundRobinArrayIndex(); - - private final Function inUseFunction; - private final System.Logger log; - - public LeastConnectedLoadBalancingStrategy( - Function inUseFunction, LoggingProvider logging) { - this.inUseFunction = inUseFunction; - this.log = logging.getLog(getClass()); - } - - @Override - public BoltServerAddress selectReader(List knownReaders) { - return select(knownReaders, readersIndex, "reader"); - } - - @Override - public BoltServerAddress selectWriter(List knownWriters) { - return select(knownWriters, writersIndex, "writer"); - } - - private BoltServerAddress select( - List addresses, RoundRobinArrayIndex addressesIndex, String addressType) { - var size = addresses.size(); - if (size == 0) { - log.log(System.Logger.Level.TRACE, "Unable to select %s, no known addresses given", addressType); - return null; - } - - // choose start index for iteration in round-robin fashion - var startIndex = addressesIndex.next(size); - var index = startIndex; - - BoltServerAddress leastConnectedAddress = null; - var leastActiveConnections = Integer.MAX_VALUE; - - // iterate over the array to find the least connected address - do { - var address = addresses.get(index); - var activeConnections = inUseFunction.apply(address); - - if (activeConnections < leastActiveConnections) { - leastConnectedAddress = address; - leastActiveConnections = activeConnections; - } - - // loop over to the start of the array when end is reached - if (index == size - 1) { - index = 0; - } else { - index++; - } - } while (index != startIndex); - - log.log( - System.Logger.Level.TRACE, - "Selected %s with address: '%s' and active connections: %s", - addressType, - leastConnectedAddress, - leastActiveConnections); - - return leastConnectedAddress; - } -} diff --git a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/loadbalancing/LoadBalancingStrategy.java b/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/loadbalancing/LoadBalancingStrategy.java deleted file mode 100644 index 51a2b497c5..0000000000 --- a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/loadbalancing/LoadBalancingStrategy.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl.cluster.loadbalancing; - -import java.util.List; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; - -/** - * A facility to select most appropriate reader or writer among the given addresses for request processing. - */ -public interface LoadBalancingStrategy { - /** - * Select most appropriate read address from the given array of addresses. - * - * @param knownReaders array of all known readers. - * @return most appropriate reader or {@code null} if it can't be selected. - */ - BoltServerAddress selectReader(List knownReaders); - - /** - * Select most appropriate write address from the given array of addresses. - * - * @param knownWriters array of all known writers. - * @return most appropriate writer or {@code null} if it can't be selected. - */ - BoltServerAddress selectWriter(List knownWriters); -} diff --git a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/loadbalancing/RoundRobinArrayIndex.java b/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/loadbalancing/RoundRobinArrayIndex.java deleted file mode 100644 index 4aabcb9a8b..0000000000 --- a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/loadbalancing/RoundRobinArrayIndex.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl.cluster.loadbalancing; - -import java.util.concurrent.atomic.AtomicInteger; - -public class RoundRobinArrayIndex { - private final AtomicInteger offset; - - RoundRobinArrayIndex() { - this(0); - } - - // only for testing - RoundRobinArrayIndex(int initialOffset) { - this.offset = new AtomicInteger(initialOffset); - } - - public int next(int arrayLength) { - if (arrayLength == 0) { - return -1; - } - - int nextOffset; - while ((nextOffset = offset.getAndIncrement()) < 0) { - // overflow, try resetting back to zero - offset.compareAndSet(nextOffset + 1, 0); - } - return nextOffset % arrayLength; - } -} diff --git a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/util/FutureUtil.java b/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/util/FutureUtil.java deleted file mode 100644 index aa22fd82fa..0000000000 --- a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/util/FutureUtil.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl.util; - -import static java.util.concurrent.CompletableFuture.completedFuture; - -import java.util.Objects; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.CompletionStage; -import java.util.function.Function; -import java.util.function.Supplier; - -public class FutureUtil { - public static CompletionException asCompletionException(Throwable error) { - if (error instanceof CompletionException) { - return ((CompletionException) error); - } - return new CompletionException(error); - } - - public static Throwable completionExceptionCause(Throwable error) { - if (error instanceof CompletionException) { - return error.getCause(); - } - return error; - } - - @SuppressWarnings("ThrowableNotThrown") - public static CompletableFuture onErrorContinue( - CompletableFuture future, - Throwable errorRecorder, - Function> onErrorAction) { - Objects.requireNonNull(future); - return future.handle((value, error) -> { - if (error != null) { - // record error - combineErrors(errorRecorder, error); - return new CompletionResult(null, error); - } - return new CompletionResult<>(value, null); - }) - .thenCompose(result -> { - if (result.value != null) { - return completedFuture(result.value); - } else { - return onErrorAction.apply(result.error); - } - }); - } - - @SuppressWarnings({"DuplicatedCode", "UnusedReturnValue"}) - public static CompletionException combineErrors(Throwable error1, Throwable error2) { - if (error1 != null && error2 != null) { - var cause1 = completionExceptionCause(error1); - var cause2 = completionExceptionCause(error2); - addSuppressed(cause1, cause2); - return asCompletionException(cause1); - } else if (error1 != null) { - return asCompletionException(error1); - } else if (error2 != null) { - return asCompletionException(error2); - } else { - return null; - } - } - - public static void addSuppressed(Throwable mainError, Throwable error) { - if (mainError != error) { - mainError.addSuppressed(error); - } - } - - public static T joinNowOrElseThrow( - CompletableFuture future, Supplier exceptionSupplier) { - if (future.isDone()) { - return future.join(); - } else { - throw exceptionSupplier.get(); - } - } - - private record CompletionResult(T value, Throwable error) {} -} diff --git a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/util/LockUtil.java b/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/util/LockUtil.java deleted file mode 100644 index be205307ad..0000000000 --- a/bolt-api-routed/src/main/java/org/neo4j/driver/internal/bolt/routedimpl/impl/util/LockUtil.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl.util; - -import java.util.concurrent.locks.Lock; -import java.util.function.Supplier; - -public class LockUtil { - public static void executeWithLock(Lock lock, Runnable runnable) { - lock(lock); - try { - runnable.run(); - } finally { - unlock(lock); - } - } - - public static T executeWithLock(Lock lock, Supplier supplier) { - lock(lock); - try { - return supplier.get(); - } finally { - unlock(lock); - } - } - - private static void lock(Lock lock) { - lock.lock(); - } - - private static void unlock(Lock lock) { - lock.unlock(); - } -} diff --git a/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/NoopLoggingProvider.java b/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/NoopLoggingProvider.java deleted file mode 100644 index b52187d7ce..0000000000 --- a/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/NoopLoggingProvider.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl; - -import static org.mockito.Mockito.mock; - -import org.neo4j.driver.internal.bolt.api.LoggingProvider; - -public class NoopLoggingProvider implements LoggingProvider { - public static final NoopLoggingProvider INSTANCE = new NoopLoggingProvider(); - - private NoopLoggingProvider() {} - - @Override - public System.Logger getLog(Class cls) { - return mock(System.Logger.class); - } - - @Override - public System.Logger getLog(String name) { - return mock(System.Logger.class); - } -} diff --git a/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/ClusterRoutingTableTest.java b/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/ClusterRoutingTableTest.java deleted file mode 100644 index 4ba14bec39..0000000000 --- a/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/ClusterRoutingTableTest.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl.cluster; - -import static java.util.Arrays.asList; -import static java.util.Collections.singletonList; -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.neo4j.driver.internal.bolt.api.AccessMode.READ; -import static org.neo4j.driver.internal.bolt.api.AccessMode.WRITE; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.A; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.B; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.C; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.D; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.E; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.EMPTY; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.F; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.createClusterComposition; - -import java.time.Clock; -import java.time.Duration; -import java.util.List; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.routedimpl.RoutingTable; -import org.neo4j.driver.internal.bolt.routedimpl.impl.util.FakeClock; - -class ClusterRoutingTableTest { - @Test - void shouldReturnStaleIfTtlExpired() { - // Given - var clock = new FakeClock(); - RoutingTable routingTable = newRoutingTable(clock); - - // When - routingTable.update(createClusterComposition(1000, asList(A, B), List.of(C), asList(D, E))); - clock.progress(1234); - - // Then - assertTrue(routingTable.isStaleFor(READ)); - assertTrue(routingTable.isStaleFor(WRITE)); - } - - @Test - void shouldReturnStaleIfNoRouter() { - // Given - RoutingTable routingTable = newRoutingTable(); - - // When - routingTable.update(createClusterComposition(EMPTY, List.of(C), asList(D, E))); - - // Then - assertTrue(routingTable.isStaleFor(READ)); - assertTrue(routingTable.isStaleFor(WRITE)); - } - - @Test - void shouldBeStaleForReadsButNotWritesWhenNoReaders() { - // Given - RoutingTable routingTable = newRoutingTable(); - - // When - routingTable.update(createClusterComposition(asList(A, B), List.of(C), EMPTY)); - - // Then - assertTrue(routingTable.isStaleFor(READ)); - assertFalse(routingTable.isStaleFor(WRITE)); - } - - @Test - void shouldBeStaleForWritesButNotReadsWhenNoWriters() { - // Given - RoutingTable routingTable = newRoutingTable(); - - // When - routingTable.update(createClusterComposition(asList(A, B), EMPTY, asList(D, E))); - - // Then - assertFalse(routingTable.isStaleFor(READ)); - assertTrue(routingTable.isStaleFor(WRITE)); - } - - @Test - void shouldBeNotStaleWithReadersWritersAndRouters() { - // Given - RoutingTable routingTable = newRoutingTable(); - - // When - routingTable.update(createClusterComposition(asList(A, B), List.of(C), asList(D, E))); - - // Then - assertFalse(routingTable.isStaleFor(READ)); - assertFalse(routingTable.isStaleFor(WRITE)); - } - - @Test - void shouldBeStaleForReadsAndWritesAfterCreation() { - // Given - var clock = new FakeClock(); - - // When - RoutingTable routingTable = new ClusterRoutingTable(defaultDatabase(), clock, A); - - // Then - assertTrue(routingTable.isStaleFor(READ)); - assertTrue(routingTable.isStaleFor(WRITE)); - } - - @ParameterizedTest - @ValueSource(strings = {"Molly", "", "I AM A NAME"}) - void shouldReturnDatabaseNameCorrectly(String db) { - // Given - var clock = new FakeClock(); - - // When - RoutingTable routingTable = new ClusterRoutingTable(database(db), clock, A); - - // Then - assertEquals(db, routingTable.database().description()); - } - - @Test - void shouldContainInitialRouters() { - // Given - var clock = new FakeClock(); - - // When - RoutingTable routingTable = new ClusterRoutingTable(defaultDatabase(), clock, A, B, C); - - // Then - assertArrayEquals( - new BoltServerAddress[] {A, B, C}, routingTable.routers().toArray()); - assertArrayEquals(new BoltServerAddress[0], routingTable.readers().toArray()); - assertArrayEquals(new BoltServerAddress[0], routingTable.writers().toArray()); - } - - @Test - void shouldPreserveOrderingOfRouters() { - var routingTable = newRoutingTable(); - var routers = asList(A, C, D, F, B, E); - - routingTable.update(createClusterComposition(routers, EMPTY, EMPTY)); - - assertArrayEquals( - new BoltServerAddress[] {A, C, D, F, B, E}, - routingTable.routers().toArray()); - } - - @Test - void shouldPreserveOrderingOfWriters() { - var routingTable = newRoutingTable(); - var writers = asList(D, F, A, C, E); - - routingTable.update(createClusterComposition(EMPTY, writers, EMPTY)); - - assertArrayEquals( - new BoltServerAddress[] {D, F, A, C, E}, routingTable.writers().toArray()); - } - - @Test - void shouldPreserveOrderingOfReaders() { - var routingTable = newRoutingTable(); - var readers = asList(B, A, F, C, D); - - routingTable.update(createClusterComposition(EMPTY, EMPTY, readers)); - - assertArrayEquals( - new BoltServerAddress[] {B, A, F, C, D}, routingTable.readers().toArray()); - } - - @Test - void shouldTreatOneRouterAsValid() { - var routingTable = newRoutingTable(); - - var routers = singletonList(A); - var writers = asList(B, C); - var readers = asList(D, E); - - routingTable.update(createClusterComposition(routers, writers, readers)); - - assertFalse(routingTable.isStaleFor(READ)); - assertFalse(routingTable.isStaleFor(WRITE)); - } - - @Test - void shouldHaveBeStaleForExpiredTime() { - var routingTable = newRoutingTable(Clock.systemUTC()); - assertTrue(routingTable.hasBeenStaleFor(0)); - } - - @Test - void shouldNotHaveBeStaleForUnexpiredTime() { - var routingTable = newRoutingTable(Clock.systemUTC()); - assertFalse(routingTable.hasBeenStaleFor(Duration.ofSeconds(30).toMillis())); - } - - @Test - void shouldDefaultToPreferInitialRouter() { - var routingTable = newRoutingTable(); - assertTrue(routingTable.preferInitialRouter()); - } - - @Test - void shouldPreferInitialRouterIfNoWriter() { - var routingTable = newRoutingTable(); - routingTable.update(createClusterComposition(EMPTY, EMPTY, EMPTY)); - assertTrue(routingTable.preferInitialRouter()); - - routingTable.update(createClusterComposition(singletonList(A), EMPTY, singletonList(A))); - assertTrue(routingTable.preferInitialRouter()); - - routingTable.update(createClusterComposition(asList(A, B), EMPTY, asList(A, B))); - assertTrue(routingTable.preferInitialRouter()); - - routingTable.update(createClusterComposition(EMPTY, EMPTY, singletonList(A))); - assertTrue(routingTable.preferInitialRouter()); - - routingTable.update(createClusterComposition(singletonList(A), EMPTY, EMPTY)); - assertTrue(routingTable.preferInitialRouter()); - } - - @Test - void shouldNotPreferInitialRouterIfHasWriter() { - var routingTable = newRoutingTable(); - routingTable.update(createClusterComposition(EMPTY, singletonList(A), EMPTY)); - assertFalse(routingTable.preferInitialRouter()); - - routingTable.update(createClusterComposition(singletonList(A), singletonList(A), singletonList(A))); - assertFalse(routingTable.preferInitialRouter()); - - routingTable.update(createClusterComposition(asList(A, B), singletonList(A), asList(A, B))); - assertFalse(routingTable.preferInitialRouter()); - - routingTable.update(createClusterComposition(EMPTY, singletonList(A), singletonList(A))); - assertFalse(routingTable.preferInitialRouter()); - - routingTable.update(createClusterComposition(singletonList(A), singletonList(A), EMPTY)); - assertFalse(routingTable.preferInitialRouter()); - } - - private ClusterRoutingTable newRoutingTable() { - return new ClusterRoutingTable(defaultDatabase(), new FakeClock()); - } - - private ClusterRoutingTable newRoutingTable(Clock clock) { - return new ClusterRoutingTable(defaultDatabase(), clock); - } -} diff --git a/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RediscoveryTest.java b/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RediscoveryTest.java deleted file mode 100644 index 171a9e3639..0000000000 --- a/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RediscoveryTest.java +++ /dev/null @@ -1,816 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl.cluster; - -import static java.util.Collections.emptySet; -import static java.util.Collections.singletonMap; -import static java.util.concurrent.CompletableFuture.completedFuture; -import static java.util.concurrent.CompletableFuture.failedFuture; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.startsWith; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.A; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.B; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.C; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.D; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.E; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.CompletionStage; -import java.util.function.Function; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import org.mockito.Mockito; -import org.mockito.stubbing.Answer; -import org.neo4j.driver.internal.bolt.api.BoltAgent; -import org.neo4j.driver.internal.bolt.api.BoltConnection; -import org.neo4j.driver.internal.bolt.api.BoltConnectionProvider; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.ClusterComposition; -import org.neo4j.driver.internal.bolt.api.DefaultDomainNameResolver; -import org.neo4j.driver.internal.bolt.api.DomainNameResolver; -import org.neo4j.driver.internal.bolt.api.GqlStatusError; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.ResponseHandler; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.SecurityPlans; -import org.neo4j.driver.internal.bolt.api.exception.BoltFailureException; -import org.neo4j.driver.internal.bolt.api.exception.BoltServiceUnavailableException; -import org.neo4j.driver.internal.bolt.api.exception.BoltUnsupportedFeatureException; -import org.neo4j.driver.internal.bolt.routedimpl.Rediscovery; -import org.neo4j.driver.internal.bolt.routedimpl.RoutingTable; -import org.neo4j.driver.internal.bolt.routedimpl.impl.AuthTokenManagerExecutionException; -import org.neo4j.driver.internal.bolt.routedimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.routedimpl.impl.util.FakeClock; - -class RediscoveryTest { - @Test - void shouldUseFirstRouterInTable() { - var expectedComposition = - new ClusterComposition(42, asOrderedSet(B, C), asOrderedSet(C, D), asOrderedSet(B), null); - - Map responsesByAddress = new HashMap<>(); - responsesByAddress.put(B, expectedComposition); // first -> valid cluster composition - - var connectionProviderGetter = connectionProviderGetter(responsesByAddress); - - var rediscovery = newRediscovery(A, Collections::singleton); - var table = routingTableMock(B); - - var actualComposition = rediscovery - .lookupClusterComposition( - SecurityPlans.unencrypted(), - table, - connectionProviderGetter, - emptySet(), - null, - null, - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join() - .getClusterComposition(); - - assertEquals(expectedComposition, actualComposition); - verify(table, never()).forget(B); - } - - @Test - void shouldSkipFailingRouters() { - var expectedComposition = - new ClusterComposition(42, asOrderedSet(A, B, C), asOrderedSet(B, C, D), asOrderedSet(A, B), null); - - Map responsesByAddress = new HashMap<>(); - responsesByAddress.put(A, new RuntimeException("Hi!")); // first -> non-fatal failure - responsesByAddress.put(B, new BoltServiceUnavailableException("Hi!")); // second -> non-fatal failure - responsesByAddress.put(C, expectedComposition); // third -> valid cluster composition - - var connectionProviderGetter = connectionProviderGetter(responsesByAddress); - - var rediscovery = newRediscovery(A, Collections::singleton); - var table = routingTableMock(A, B, C); - - var actualComposition = rediscovery - .lookupClusterComposition( - SecurityPlans.unencrypted(), - table, - connectionProviderGetter, - emptySet(), - null, - null, - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join() - .getClusterComposition(); - - assertEquals(expectedComposition, actualComposition); - verify(table).forget(A); - verify(table).forget(B); - verify(table, never()).forget(C); - } - - @Test - void shouldFailImmediatelyOnAuthError() { - var authError = new BoltFailureException( - "Neo.ClientError.Security.Unauthorized", - "Wrong password", - GqlStatusError.UNKNOWN.getStatus(), - GqlStatusError.UNKNOWN.getStatusDescription(""), - Collections.emptyMap(), - null); - - Map responsesByAddress = new HashMap<>(); - responsesByAddress.put(A, new RuntimeException("Hi!")); // first router -> non-fatal failure - responsesByAddress.put(B, authError); // second router -> fatal auth error - - var connectionProviderGetter = connectionProviderGetter(responsesByAddress); - var rediscovery = newRediscovery(A, Collections::singleton); - var table = routingTableMock(A, B, C); - - Throwable error = assertThrows(CompletionException.class, () -> rediscovery - .lookupClusterComposition( - SecurityPlans.unencrypted(), - table, - connectionProviderGetter, - emptySet(), - null, - null, - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join()); - error = error.getCause(); - assertInstanceOf(BoltFailureException.class, error); - assertEquals(authError, error); - verify(table).forget(A); - } - - @Test - void shouldUseAnotherRouterOnAuthorizationExpiredException() { - var expectedComposition = - new ClusterComposition(42, asOrderedSet(A, B, C), asOrderedSet(B, C, D), asOrderedSet(A, B), null); - - Map responsesByAddress = new HashMap<>(); - responsesByAddress.put( - A, - new BoltFailureException( - "Neo.ClientError.Security.AuthorizationExpired", - "message", - GqlStatusError.UNKNOWN.getStatus(), - GqlStatusError.UNKNOWN.getStatusDescription(""), - Collections.emptyMap(), - null)); - responsesByAddress.put(B, expectedComposition); - - var connectionProviderGetter = connectionProviderGetter(responsesByAddress); - var rediscovery = newRediscovery(A, Collections::singleton); - var table = routingTableMock(A, B, C); - - var actualComposition = rediscovery - .lookupClusterComposition( - SecurityPlans.unencrypted(), - table, - connectionProviderGetter, - emptySet(), - null, - null, - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join() - .getClusterComposition(); - - assertEquals(expectedComposition, actualComposition); - verify(table).forget(A); - verify(table, never()).forget(B); - verify(table, never()).forget(C); - } - - @ParameterizedTest - @ValueSource( - strings = { - "Neo.ClientError.Transaction.InvalidBookmark", - "Neo.ClientError.Transaction.InvalidBookmarkMixture" - }) - void shouldFailImmediatelyOnBookmarkErrors(String code) { - var error = new BoltFailureException( - code, - "Invalid", - GqlStatusError.UNKNOWN.getStatus(), - GqlStatusError.UNKNOWN.getStatusDescription(""), - Collections.emptyMap(), - null); - - Map responsesByAddress = new HashMap<>(); - responsesByAddress.put(A, new RuntimeException("Hi!")); - responsesByAddress.put(B, error); - - var connectionProviderGetter = connectionProviderGetter(responsesByAddress); - var rediscovery = newRediscovery(A, Collections::singleton); - var table = routingTableMock(A, B, C); - - Throwable actualError = assertThrows(CompletionException.class, () -> rediscovery - .lookupClusterComposition( - SecurityPlans.unencrypted(), - table, - connectionProviderGetter, - emptySet(), - null, - null, - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join()); - actualError = actualError.getCause(); - assertInstanceOf(BoltFailureException.class, actualError); - assertEquals(error, actualError); - verify(table).forget(A); - } - - @Test - void shouldFailImmediatelyOnClosedPoolError() { - var error = new IllegalStateException("Connection provider is closed."); - - Map responsesByAddress = new HashMap<>(); - responsesByAddress.put(A, new RuntimeException("Hi!")); - responsesByAddress.put(B, error); - - var connectionProviderGetter = connectionProviderGetter(responsesByAddress); - var rediscovery = newRediscovery(A, Collections::singleton); - var table = routingTableMock(A, B, C); - - Throwable actualError = assertThrows(CompletionException.class, () -> rediscovery - .lookupClusterComposition( - SecurityPlans.unencrypted(), - table, - connectionProviderGetter, - emptySet(), - null, - null, - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join()); - actualError = actualError.getCause(); - assertInstanceOf(IllegalStateException.class, actualError); - assertEquals(error, actualError); - verify(table).forget(A); - } - - @Test - void shouldFallbackToInitialRouterWhenKnownRoutersFail() { - var initialRouter = A; - var expectedComposition = - new ClusterComposition(42, asOrderedSet(C, B, A), asOrderedSet(A, B), asOrderedSet(D, E), null); - - Map responsesByAddress = new HashMap<>(); - responsesByAddress.put(B, new BoltServiceUnavailableException("Hi!")); // first -> non-fatal failure - responsesByAddress.put(C, new BoltServiceUnavailableException("Hi!")); // second -> non-fatal failure - responsesByAddress.put(initialRouter, expectedComposition); // initial -> valid response - - var connectionProviderGetter = connectionProviderGetter(responsesByAddress); - var resolver = resolverMock(initialRouter, initialRouter); - var rediscovery = newRediscovery(initialRouter, resolver); - var table = routingTableMock(B, C); - - var actualComposition = rediscovery - .lookupClusterComposition( - SecurityPlans.unencrypted(), - table, - connectionProviderGetter, - emptySet(), - null, - null, - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join() - .getClusterComposition(); - - assertEquals(expectedComposition, actualComposition); - verify(table).forget(B); - verify(table).forget(C); - } - - @Test - void shouldResolveInitialRouterAddress() { - var initialRouter = A; - var expectedComposition = - new ClusterComposition(42, asOrderedSet(A, B), asOrderedSet(A, B), asOrderedSet(A, B), null); - - Map responsesByAddress = new HashMap<>(); - responsesByAddress.put(B, new BoltServiceUnavailableException("Hi!")); // first -> non-fatal failure - responsesByAddress.put(C, new BoltServiceUnavailableException("Hi!")); // second -> non-fatal failure - responsesByAddress.put(D, new IOException("Hi!")); // resolved first -> non-fatal failure - responsesByAddress.put(E, expectedComposition); // resolved second -> valid response - - var connectionProviderGetter = connectionProviderGetter(responsesByAddress); - // initial router resolved to two other addresses - var resolver = resolverMock(initialRouter, D, E); - var rediscovery = newRediscovery(initialRouter, resolver); - var table = routingTableMock(B, C); - - var actualComposition = rediscovery - .lookupClusterComposition( - SecurityPlans.unencrypted(), - table, - connectionProviderGetter, - emptySet(), - null, - null, - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join() - .getClusterComposition(); - - assertEquals(expectedComposition, actualComposition); - verify(table).forget(B); - verify(table).forget(C); - verify(table).forget(D); - } - - @Test - void shouldResolveInitialRouterAddressUsingCustomResolver() { - var expectedComposition = - new ClusterComposition(42, asOrderedSet(A, B, C), asOrderedSet(A, B, C), asOrderedSet(B, E), null); - - Function> resolver = address -> { - assertEquals(A, address); - return asOrderedSet(B, C, E); - }; - - Map responsesByAddress = new HashMap<>(); - responsesByAddress.put(B, new BoltServiceUnavailableException("Hi!")); // first -> non-fatal failure - responsesByAddress.put(C, new BoltServiceUnavailableException("Hi!")); // second -> non-fatal failure - responsesByAddress.put(E, expectedComposition); // resolved second -> valid response - - var connectionProviderGetter = connectionProviderGetter(responsesByAddress); - var rediscovery = newRediscovery(A, resolver); - var table = routingTableMock(B, C); - - var actualComposition = rediscovery - .lookupClusterComposition( - SecurityPlans.unencrypted(), - table, - connectionProviderGetter, - emptySet(), - null, - null, - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join() - .getClusterComposition(); - - assertEquals(expectedComposition, actualComposition); - verify(table).forget(B); - verify(table).forget(C); - } - - @Test - void shouldPropagateFailureWhenResolverFails() { - var expectedComposition = - new ClusterComposition(42, asOrderedSet(A, B), asOrderedSet(A, B), asOrderedSet(A, B), null); - - Map responsesByAddress = singletonMap(A, expectedComposition); - var connectionProviderGetter = connectionProviderGetter(responsesByAddress); - - // failing server address resolver - @SuppressWarnings("unchecked") - Function> resolver = mock(Function.class); - when(resolver.apply(A)).thenThrow(new RuntimeException("Resolver fails!")); - - var rediscovery = newRediscovery(A, resolver); - var table = routingTableMock(); - - Throwable error = assertThrows(CompletionException.class, () -> rediscovery - .lookupClusterComposition( - SecurityPlans.unencrypted(), - table, - connectionProviderGetter, - emptySet(), - null, - null, - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join()); - error = error.getCause(); - assertEquals("Resolver fails!", error.getMessage()); - - verify(resolver).apply(A); - verify(table, never()).forget(any()); - } - - @Test - void shouldRecordAllErrorsWhenNoRouterRespond() { - Map responsesByAddress = new HashMap<>(); - var first = new BoltServiceUnavailableException("Hi!"); - responsesByAddress.put(A, first); // first -> non-fatal failure - var second = new BoltServiceUnavailableException("Hi!"); - responsesByAddress.put(B, second); // second -> non-fatal failure - var third = new IOException("Hi!"); - responsesByAddress.put(C, third); // third -> non-fatal failure - - var connectionProviderGetter = connectionProviderGetter(responsesByAddress); - var rediscovery = newRediscovery(A, Collections::singleton); - var table = routingTableMock(A, B, C); - - Throwable e = assertThrows(CompletionException.class, () -> rediscovery - .lookupClusterComposition( - SecurityPlans.unencrypted(), - table, - connectionProviderGetter, - emptySet(), - null, - null, - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join()); - e = e.getCause(); - assertInstanceOf(BoltServiceUnavailableException.class, e); - assertTrue(e.getMessage().contains("Could not perform discovery")); - assertEquals(3, e.getSuppressed().length); - assertEquals(first, e.getSuppressed()[0].getCause()); - assertEquals(second, e.getSuppressed()[1].getCause()); - assertEquals(third, e.getSuppressed()[2].getCause()); - } - - @Test - void shouldUseInitialRouterAfterDiscoveryReturnsNoWriters() { - var initialRouter = A; - var noWritersComposition = new ClusterComposition(42, asOrderedSet(D, E), emptySet(), asOrderedSet(D, E), null); - var validComposition = - new ClusterComposition(42, asOrderedSet(B, A), asOrderedSet(B, A), asOrderedSet(B, A), null); - - Map responsesByAddress = new HashMap<>(); - responsesByAddress.put(initialRouter, validComposition); // initial -> valid composition - - var connectionProviderGetter = connectionProviderGetter(responsesByAddress); - var resolver = resolverMock(initialRouter, initialRouter); - var rediscovery = newRediscovery(initialRouter, resolver); - RoutingTable table = new ClusterRoutingTable(defaultDatabase(), new FakeClock()); - table.update(noWritersComposition); - - var composition2 = rediscovery - .lookupClusterComposition( - SecurityPlans.unencrypted(), - table, - connectionProviderGetter, - emptySet(), - null, - null, - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join() - .getClusterComposition(); - assertEquals(validComposition, composition2); - } - - @Test - void shouldUseInitialRouterToStartWith() { - var initialRouter = A; - var validComposition = new ClusterComposition(42, asOrderedSet(A), asOrderedSet(A), asOrderedSet(A), null); - - Map responsesByAddress = new HashMap<>(); - responsesByAddress.put(initialRouter, validComposition); // initial -> valid composition - - var connectionProviderGetter = connectionProviderGetter(responsesByAddress); - var resolver = resolverMock(initialRouter, initialRouter); - var rediscovery = newRediscovery(initialRouter, resolver); - var table = routingTableMock(true, B, C, D); - - var composition = rediscovery - .lookupClusterComposition( - SecurityPlans.unencrypted(), - table, - connectionProviderGetter, - Collections.emptySet(), - null, - null, - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join() - .getClusterComposition(); - assertEquals(validComposition, composition); - } - - @Test - void shouldUseKnownRoutersWhenInitialRouterFails() { - var initialRouter = A; - var validComposition = - new ClusterComposition(42, asOrderedSet(D, E), asOrderedSet(E, D), asOrderedSet(A, B), null); - - Map responsesByAddress = new HashMap<>(); - responsesByAddress.put(initialRouter, new BoltServiceUnavailableException("Hi")); // initial -> non-fatal error - responsesByAddress.put(D, new IOException("Hi")); // first known -> non-fatal failure - responsesByAddress.put(E, validComposition); // second known -> valid composition - - var connectionProviderGetter = connectionProviderGetter(responsesByAddress); - var resolver = resolverMock(initialRouter, initialRouter); - var rediscovery = newRediscovery(initialRouter, resolver); - var table = routingTableMock(true, D, E); - - var composition = rediscovery - .lookupClusterComposition( - SecurityPlans.unencrypted(), - table, - connectionProviderGetter, - Collections.emptySet(), - null, - null, - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join() - .getClusterComposition(); - assertEquals(validComposition, composition); - verify(table).forget(initialRouter); - verify(table).forget(D); - } - - @Test - void shouldNotLogWhenSingleRetryAttemptFails() { - Map responsesByAddress = singletonMap(A, new BoltServiceUnavailableException("Hi!")); - var connectionProviderGetter = connectionProviderGetter(responsesByAddress); - var resolver = resolverMock(A, A); - - var logging = mock(LoggingProvider.class); - var logger = mock(System.Logger.class); - when(logging.getLog(any(Class.class))).thenReturn(logger); - Rediscovery rediscovery = new RediscoveryImpl( - A, - resolver, - logging, - DefaultDomainNameResolver.getInstance(), - RoutingContext.EMPTY, - mock(BoltAgent.class), - "userAgent", - 0); - var table = routingTableMock(A); - - Throwable e = assertThrows(CompletionException.class, () -> rediscovery - .lookupClusterComposition( - SecurityPlans.unencrypted(), - table, - connectionProviderGetter, - Collections.emptySet(), - null, - null, - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join()); - e = e.getCause(); - assertInstanceOf(BoltServiceUnavailableException.class, e); - assertTrue(e.getMessage().contains("Could not perform discovery")); - - // rediscovery should not log about retries and should not schedule any retries - verify(logging).getLog(RediscoveryImpl.class); - verify(logger, never()) - .log(eq(System.Logger.Level.INFO), startsWith("Unable to fetch new routing table, will try again in ")); - } - - @Test - void shouldResolveToIP() throws UnknownHostException { - var resolver = resolverMock(A, A); - var domainNameResolver = mock(DomainNameResolver.class); - var localhost = InetAddress.getLocalHost(); - when(domainNameResolver.resolve(A.host())).thenReturn(new InetAddress[] {localhost}); - Rediscovery rediscovery = new RediscoveryImpl( - A, - resolver, - NoopLoggingProvider.INSTANCE, - domainNameResolver, - RoutingContext.EMPTY, - mock(BoltAgent.class), - "userAgent", - 0); - - var addresses = rediscovery.resolve(); - - verify(resolver, times(1)).apply(A); - verify(domainNameResolver, times(1)).resolve(A.host()); - assertEquals(1, addresses.size()); - assertEquals(new BoltServerAddress(A.host(), localhost.getHostAddress(), A.port()), addresses.get(0)); - } - - @Test - void shouldFailImmediatelyOnAuthTokenManagerExecutionException() { - var exception = new AuthTokenManagerExecutionException(new RuntimeException()); - - Map responsesByAddress = new HashMap<>(); - responsesByAddress.put(A, new RuntimeException("Hi!")); // first router -> non-fatal failure - responsesByAddress.put(B, exception); // second router -> fatal auth error - - var connectionProviderGetter = connectionProviderGetter(responsesByAddress); - var rediscovery = newRediscovery(A, Collections::singleton); - var table = routingTableMock(A, B, C); - - Throwable actualException = assertThrows(CompletionException.class, () -> rediscovery - .lookupClusterComposition( - SecurityPlans.unencrypted(), - table, - connectionProviderGetter, - Collections.emptySet(), - null, - null, - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join()); - actualException = actualException.getCause(); - assertInstanceOf(AuthTokenManagerExecutionException.class, actualException); - assertEquals(exception, actualException); - verify(table).forget(A); - } - - @Test - void shouldFailImmediatelyOnUnsupportedFeatureException() { - var exception = new BoltUnsupportedFeatureException("message"); - - Map responsesByAddress = new HashMap<>(); - responsesByAddress.put(A, new RuntimeException("Hi!")); // first router -> non-fatal failure - responsesByAddress.put(B, exception); // second router -> fatal auth error - - var connectionProviderGetter = connectionProviderGetter(responsesByAddress); - var rediscovery = newRediscovery(A, Collections::singleton); - var table = routingTableMock(A, B, C); - - Throwable actualException = assertThrows(CompletionException.class, () -> rediscovery - .lookupClusterComposition( - SecurityPlans.unencrypted(), - table, - connectionProviderGetter, - Collections.emptySet(), - null, - null, - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join()); - actualException = actualException.getCause(); - assertInstanceOf(BoltUnsupportedFeatureException.class, actualException); - assertEquals(exception, actualException); - verify(table).forget(A); - } - - @Test - void shouldLogScopedIPV6AddressWithStringFormattingLogger() throws UnknownHostException { - // GIVEN - var initialRouter = new BoltServerAddress("initialRouter", 7687); - var connectionProviderGetter = connectionProviderGetter(Collections.emptyMap()); - var resolver = resolverMock(initialRouter, initialRouter); - var domainNameResolver = mock(DomainNameResolver.class); - var address = mock(InetAddress.class); - given(address.getHostAddress()).willReturn("fe80:0:0:0:ce66:1564:db8q:94b6%6"); - given(domainNameResolver.resolve(initialRouter.host())).willReturn(new InetAddress[] {address}); - var table = routingTableMock(true); - var pool = mock(BoltConnectionProvider.class); - given(pool.connect( - any(), any(), any(), any(), anyInt(), any(), any(), any(), any(), any(), any(), any(), any(), - any(), any())) - .willReturn(failedFuture(new BoltServiceUnavailableException("not available"))); - var logging = mock(LoggingProvider.class); - var logger = mock(System.Logger.class); - given(logging.getLog(any(Class.class))).willReturn(logger); - doAnswer(invocationOnMock -> String.format(invocationOnMock.getArgument(0), invocationOnMock.getArgument(1))) - .when(logger) - .log(eq(System.Logger.Level.WARNING), anyString()); - var rediscovery = new RediscoveryImpl( - initialRouter, - resolver, - logging, - domainNameResolver, - RoutingContext.EMPTY, - mock(BoltAgent.class), - "userAgent", - 0); - - // WHEN & THEN - Throwable e = assertThrows(CompletionException.class, () -> rediscovery - .lookupClusterComposition( - SecurityPlans.unencrypted(), - table, - connectionProviderGetter, - Collections.emptySet(), - null, - null, - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join()); - e = e.getCause(); - assertInstanceOf(BoltServiceUnavailableException.class, e); - } - - private Rediscovery newRediscovery( - BoltServerAddress initialRouter, Function> resolver) { - return newRediscovery(initialRouter, resolver, NoopLoggingProvider.INSTANCE); - } - - @SuppressWarnings("SameParameterValue") - private Rediscovery newRediscovery( - BoltServerAddress initialRouter, - Function> resolver, - LoggingProvider loggingProvider) { - return new RediscoveryImpl( - initialRouter, - resolver, - loggingProvider, - DefaultDomainNameResolver.getInstance(), - RoutingContext.EMPTY, - mock(BoltAgent.class), - "userAgent", - 0); - } - - private Function connectionProviderGetter( - Map responsesByAddress) { - var addressToProvider = new HashMap(); - for (var entry : responsesByAddress.entrySet()) { - var boltConnection = setupConnection(entry.getValue()); - - var boltConnectionProvider = mock(BoltConnectionProvider.class); - given(boltConnectionProvider.connect( - any(), any(), any(), any(), anyInt(), any(), any(), any(), any(), any(), any(), any(), - any(), any(), any())) - .willReturn(completedFuture(boltConnection)); - - addressToProvider.put(entry.getKey(), boltConnectionProvider); - } - return addressToProvider::get; - } - - private BoltConnection setupConnection(Object answer) { - var boltConnection = mock(BoltConnection.class); - given(boltConnection.route(any(), any(), any())).willReturn(CompletableFuture.completedStage(boltConnection)); - given(boltConnection.flush(any())).willAnswer((Answer>) invocationOnMock -> { - var handler = (ResponseHandler) invocationOnMock.getArguments()[0]; - - if (answer instanceof ClusterComposition composition) { - handler.onRouteSummary(() -> composition); - } else if (answer instanceof Throwable throwable) { - handler.onError(throwable); - } - handler.onComplete(); - - return CompletableFuture.completedStage(null); - }); - given(boltConnection.close()).willReturn(CompletableFuture.completedStage(null)); - return boltConnection; - } - - private static Function> resolverMock( - BoltServerAddress address, BoltServerAddress... resolved) { - @SuppressWarnings("unchecked") - Function> resolverMock = Mockito.mock(Function.class); - given(resolverMock.apply(address)).willReturn(asOrderedSet(resolved)); - return resolverMock; - } - - private static RoutingTable routingTableMock(BoltServerAddress... routers) { - return routingTableMock(false, routers); - } - - private static RoutingTable routingTableMock(boolean preferInitialRouter, BoltServerAddress... routers) { - var routingTable = Mockito.mock(RoutingTable.class); - when(routingTable.routers()).thenReturn(Arrays.asList(routers)); - when(routingTable.database()).thenReturn(defaultDatabase()); - when(routingTable.preferInitialRouter()).thenReturn(preferInitialRouter); - return routingTable; - } - - @SafeVarargs - @SuppressWarnings("varargs") - public static Set asOrderedSet(T... elements) { - return new LinkedHashSet<>(Arrays.asList(elements)); - } -} diff --git a/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RoutingTableHandlerTest.java b/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RoutingTableHandlerTest.java deleted file mode 100644 index 969bf60a84..0000000000 --- a/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RoutingTableHandlerTest.java +++ /dev/null @@ -1,462 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl.cluster; - -import static java.util.Arrays.asList; -import static java.util.Collections.emptySet; -import static java.util.Collections.singletonList; -import static java.util.concurrent.CompletableFuture.completedFuture; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.api.AccessMode.READ; -import static org.neo4j.driver.internal.bolt.api.AccessMode.WRITE; -import static org.neo4j.driver.internal.bolt.api.BoltServerAddress.LOCAL_DEFAULT; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.A; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.B; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.C; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.D; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.E; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.F; - -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.AuthToken; -import org.neo4j.driver.internal.bolt.api.AuthTokens; -import org.neo4j.driver.internal.bolt.api.BoltConnection; -import org.neo4j.driver.internal.bolt.api.BoltConnectionProvider; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.ClusterComposition; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; -import org.neo4j.driver.internal.bolt.api.SecurityPlans; -import org.neo4j.driver.internal.bolt.api.exception.BoltServiceUnavailableException; -import org.neo4j.driver.internal.bolt.routedimpl.ClusterCompositionLookupResult; -import org.neo4j.driver.internal.bolt.routedimpl.Rediscovery; -import org.neo4j.driver.internal.bolt.routedimpl.RoutingTable; -import org.neo4j.driver.internal.bolt.routedimpl.impl.NoopLoggingProvider; -import org.neo4j.driver.internal.bolt.routedimpl.impl.util.FakeClock; - -class RoutingTableHandlerTest { - public static final long STALE_ROUTING_TABLE_PURGE_DELAY_MS = SECONDS.toMillis(30); - - @Test - void shouldRemoveAddressFromRoutingTableOnConnectionFailure() { - RoutingTable routingTable = new ClusterRoutingTable(defaultDatabase(), new FakeClock()); - routingTable.update( - new ClusterComposition(42, asOrderedSet(A, B, C), asOrderedSet(A, C, E), asOrderedSet(B, D, F), null)); - - var handler = newRoutingTableHandler(routingTable, newRediscoveryMock(), newConnectionPoolMock()); - - handler.onConnectionFailure(B); - - assertArrayEquals(new BoltServerAddress[] {A, C}, routingTable.readers().toArray()); - assertArrayEquals( - new BoltServerAddress[] {A, C, E}, routingTable.writers().toArray()); - assertArrayEquals(new BoltServerAddress[] {D, F}, routingTable.routers().toArray()); - - handler.onConnectionFailure(A); - - assertArrayEquals(new BoltServerAddress[] {C}, routingTable.readers().toArray()); - assertArrayEquals(new BoltServerAddress[] {C, E}, routingTable.writers().toArray()); - assertArrayEquals(new BoltServerAddress[] {D, F}, routingTable.routers().toArray()); - } - - @Test - void acquireShouldUpdateRoutingTableWhenKnownRoutingTableIsStale() { - var initialRouter = new BoltServerAddress("initialRouter", 1); - var reader1 = new BoltServerAddress("reader-1", 2); - var reader2 = new BoltServerAddress("reader-1", 3); - var writer1 = new BoltServerAddress("writer-1", 4); - var router1 = new BoltServerAddress("router-1", 5); - - var connectionPool = newConnectionPoolMock(); - var routingTable = new ClusterRoutingTable(defaultDatabase(), new FakeClock(), initialRouter); - - Set readers = new LinkedHashSet<>(asList(reader1, reader2)); - Set writers = new LinkedHashSet<>(singletonList(writer1)); - Set routers = new LinkedHashSet<>(singletonList(router1)); - var clusterComposition = new ClusterComposition(42, readers, writers, routers, null); - Rediscovery rediscovery = Mockito.mock(RediscoveryImpl.class); - when(rediscovery.lookupClusterComposition( - any(), eq(routingTable), eq(connectionPool), any(), any(), any(), any())) - .thenReturn(completedFuture(new ClusterCompositionLookupResult(clusterComposition))); - - var handler = newRoutingTableHandler(routingTable, rediscovery, connectionPool); - assertNotNull(handler.ensureRoutingTable( - SecurityPlans.unencrypted(), - READ, - Collections.emptySet(), - () -> CompletableFuture.completedStage(AuthTokens.custom(Collections.emptyMap())), - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join()); - - verify(rediscovery) - .lookupClusterComposition(any(), eq(routingTable), eq(connectionPool), any(), any(), any(), any()); - assertArrayEquals( - new BoltServerAddress[] {reader1, reader2}, - routingTable.readers().toArray()); - assertArrayEquals( - new BoltServerAddress[] {writer1}, routingTable.writers().toArray()); - assertArrayEquals( - new BoltServerAddress[] {router1}, routingTable.routers().toArray()); - } - - @Test - void shouldRediscoverOnReadWhenRoutingTableIsStaleForReads() { - testRediscoveryWhenStale(READ); - } - - @Test - void shouldRediscoverOnWriteWhenRoutingTableIsStaleForWrites() { - testRediscoveryWhenStale(WRITE); - } - - @Test - void shouldNotRediscoverOnReadWhenRoutingTableIsStaleForWritesButNotReads() { - testNoRediscoveryWhenNotStale(WRITE, READ); - } - - @Test - void shouldNotRediscoverOnWriteWhenRoutingTableIsStaleForReadsButNotWrites() { - testNoRediscoveryWhenNotStale(READ, WRITE); - } - - @Test - void shouldRetainAllFetchedAddressesInConnectionPoolAfterFetchingOfRoutingTable() { - RoutingTable routingTable = new ClusterRoutingTable(defaultDatabase(), new FakeClock()); - routingTable.update(new ClusterComposition(42, asOrderedSet(), asOrderedSet(B, C), asOrderedSet(D, E), null)); - - var connectionPool = newConnectionPoolMock(); - - var rediscovery = newRediscoveryMock(); - when(rediscovery.lookupClusterComposition(any(), any(), any(), any(), any(), any(), any())) - .thenReturn(completedFuture(new ClusterCompositionLookupResult( - new ClusterComposition(42, asOrderedSet(A, B), asOrderedSet(B, C), asOrderedSet(A, C), null)))); - - var registry = new RoutingTableRegistry() { - @Override - public CompletionStage ensureRoutingTable( - SecurityPlan securityPlan, - CompletableFuture databaseNameFuture, - AccessMode mode, - Set rediscoveryBookmarks, - String impersonatedUser, - Supplier> authTokenStageSupplier, - BoltProtocolVersion minVersion, - String homeDatabaseHint) { - throw new UnsupportedOperationException(); - } - - @Override - public Set allServers() { - return routingTable.servers(); - } - - @Override - public void remove(DatabaseName databaseName) { - throw new UnsupportedOperationException(); - } - - @Override - public void removeAged() {} - - @Override - public Optional getRoutingTableHandler(DatabaseName databaseName) { - return Optional.empty(); - } - }; - - var addressesToRetainRef = new AtomicReference>(); - var handler = - newRoutingTableHandler(routingTable, rediscovery, connectionPool, registry, addressesToRetainRef::set); - - var actual = handler.ensureRoutingTable( - SecurityPlans.unencrypted(), - READ, - Collections.emptySet(), - () -> CompletableFuture.completedStage(AuthTokens.custom(Collections.emptyMap())), - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join(); - assertEquals(routingTable, actual); - - assertEquals(Set.of(A, B, C), addressesToRetainRef.get()); - } - - @Test - void shouldRemoveRoutingTableHandlerIfFailedToLookup() { - // Given - RoutingTable routingTable = new ClusterRoutingTable(defaultDatabase(), new FakeClock()); - - var rediscovery = newRediscoveryMock(); - when(rediscovery.lookupClusterComposition(any(), any(), any(), any(), any(), any(), any())) - .thenReturn(CompletableFuture.failedFuture(new RuntimeException("Bang!"))); - - var connectionPool = newConnectionPoolMock(); - var registry = newRoutingTableRegistryMock(); - // When - - var handler = newRoutingTableHandler(routingTable, rediscovery, connectionPool, registry); - assertThrows(RuntimeException.class, () -> handler.ensureRoutingTable( - SecurityPlans.unencrypted(), - READ, - Collections.emptySet(), - () -> CompletableFuture.completedStage(AuthTokens.custom(Collections.emptyMap())), - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join()); - - // Then - verify(registry).remove(defaultDatabase()); - } - - private void testRediscoveryWhenStale(AccessMode mode) { - Function connectionProviderGetter = requestedAddress -> { - var boltConnectionProvider = mock(BoltConnectionProvider.class); - var connection = mock(BoltConnection.class); - given(boltConnectionProvider.connect( - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - Collections.emptyMap())) - .willReturn(completedFuture(connection)); - return boltConnectionProvider; - }; - - var routingTable = newStaleRoutingTableMock(mode); - var rediscovery = newRediscoveryMock(); - - var handler = newRoutingTableHandler(routingTable, rediscovery, connectionProviderGetter); - var actual = handler.ensureRoutingTable( - SecurityPlans.unencrypted(), - mode, - Collections.emptySet(), - () -> CompletableFuture.completedStage(AuthTokens.custom(Collections.emptyMap())), - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join(); - assertEquals(routingTable, actual); - - verify(routingTable).isStaleFor(mode); - verify(rediscovery) - .lookupClusterComposition( - any(), eq(routingTable), eq(connectionProviderGetter), any(), any(), any(), any()); - } - - private void testNoRediscoveryWhenNotStale(AccessMode staleMode, AccessMode notStaleMode) { - Function connectionProviderGetter = requestedAddress -> { - var boltConnectionProvider = mock(BoltConnectionProvider.class); - var connection = mock(BoltConnection.class); - given(boltConnectionProvider.connect( - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - Collections.emptyMap())) - .willReturn(completedFuture(connection)); - return boltConnectionProvider; - }; - - var routingTable = newStaleRoutingTableMock(staleMode); - var rediscovery = newRediscoveryMock(); - - var handler = newRoutingTableHandler(routingTable, rediscovery, connectionProviderGetter); - - assertNotNull(handler.ensureRoutingTable( - SecurityPlans.unencrypted(), - notStaleMode, - Collections.emptySet(), - () -> CompletableFuture.completedStage(AuthTokens.custom(Collections.emptyMap())), - new BoltProtocolVersion(4, 1)) - .toCompletableFuture() - .join()); - verify(routingTable).isStaleFor(notStaleMode); - verify(rediscovery, never()) - .lookupClusterComposition( - any(), eq(routingTable), eq(connectionProviderGetter), any(), any(), any(), any()); - } - - private static RoutingTable newStaleRoutingTableMock(AccessMode mode) { - var routingTable = Mockito.mock(RoutingTable.class); - when(routingTable.isStaleFor(mode)).thenReturn(true); - - var addresses = singletonList(LOCAL_DEFAULT); - when(routingTable.readers()).thenReturn(addresses); - when(routingTable.writers()).thenReturn(addresses); - when(routingTable.database()).thenReturn(defaultDatabase()); - - return routingTable; - } - - private static RoutingTableRegistry newRoutingTableRegistryMock() { - return Mockito.mock(RoutingTableRegistry.class); - } - - @SuppressWarnings("unchecked") - private static Rediscovery newRediscoveryMock() { - Rediscovery rediscovery = Mockito.mock(RediscoveryImpl.class); - Set noServers = Collections.emptySet(); - var clusterComposition = new ClusterComposition(1, noServers, noServers, noServers, null); - when(rediscovery.lookupClusterComposition( - any(), any(RoutingTable.class), any(Function.class), any(), any(), any(), any())) - .thenReturn(completedFuture(new ClusterCompositionLookupResult(clusterComposition))); - return rediscovery; - } - - private static Function newConnectionPoolMock() { - return newConnectionPoolMockWithFailures(emptySet()); - } - - private static Function newConnectionPoolMockWithFailures( - Set unavailableAddresses) { - return requestedAddress -> { - var boltConnectionProvider = mock(BoltConnectionProvider.class); - if (unavailableAddresses.contains(requestedAddress)) { - given(boltConnectionProvider.connect( - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - Collections.emptyMap())) - .willReturn(CompletableFuture.failedFuture( - new BoltServiceUnavailableException(requestedAddress + " is unavailable!"))); - return boltConnectionProvider; - } - var connection = mock(BoltConnection.class); - when(connection.serverAddress()).thenReturn(requestedAddress); - given(boltConnectionProvider.connect( - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - any(), - Collections.emptyMap())) - .willReturn(completedFuture(connection)); - return boltConnectionProvider; - }; - } - - private static RoutingTableHandler newRoutingTableHandler( - RoutingTable routingTable, - Rediscovery rediscovery, - Function connectionProviderGetter) { - return new RoutingTableHandlerImpl( - routingTable, - rediscovery, - connectionProviderGetter, - newRoutingTableRegistryMock(), - NoopLoggingProvider.INSTANCE, - STALE_ROUTING_TABLE_PURGE_DELAY_MS, - ignored -> {}); - } - - private static RoutingTableHandler newRoutingTableHandler( - RoutingTable routingTable, - Rediscovery rediscovery, - Function connectionProviderGetter, - RoutingTableRegistry routingTableRegistry) { - return newRoutingTableHandler( - routingTable, rediscovery, connectionProviderGetter, routingTableRegistry, ignored -> {}); - } - - private static RoutingTableHandler newRoutingTableHandler( - RoutingTable routingTable, - Rediscovery rediscovery, - Function connectionProviderGetter, - RoutingTableRegistry routingTableRegistry, - Consumer> addressesToRetainConsumer) { - return new RoutingTableHandlerImpl( - routingTable, - rediscovery, - connectionProviderGetter, - routingTableRegistry, - NoopLoggingProvider.INSTANCE, - STALE_ROUTING_TABLE_PURGE_DELAY_MS, - addressesToRetainConsumer); - } - - @SafeVarargs - @SuppressWarnings("varargs") - public static Set asOrderedSet(T... elements) { - return new LinkedHashSet<>(Arrays.asList(elements)); - } -} diff --git a/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RoutingTableRegistryImplTest.java b/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RoutingTableRegistryImplTest.java deleted file mode 100644 index 71654b9e75..0000000000 --- a/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/RoutingTableRegistryImplTest.java +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl.cluster; - -import static java.util.concurrent.CompletableFuture.completedFuture; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.SYSTEM_DATABASE_NAME; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.A; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.B; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.C; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.D; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.E; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.F; - -import java.time.Clock; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.function.Supplier; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.junit.jupiter.params.provider.ValueSource; -import org.mockito.Mockito; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.AuthToken; -import org.neo4j.driver.internal.bolt.api.AuthTokens; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.SecurityPlans; -import org.neo4j.driver.internal.bolt.routedimpl.Rediscovery; -import org.neo4j.driver.internal.bolt.routedimpl.RoutingTable; -import org.neo4j.driver.internal.bolt.routedimpl.impl.NoopLoggingProvider; - -class RoutingTableRegistryImplTest { - public static final long STALE_ROUTING_TABLE_PURGE_DELAY_MS = SECONDS.toMillis(30); - - @Test - void factoryShouldCreateARoutingTableWithSameDatabaseName() { - var clock = Clock.systemUTC(); - var factory = new RoutingTableRegistryImpl.RoutingTableHandlerFactory( - mock(), - Mockito.mock(RediscoveryImpl.class), - clock, - NoopLoggingProvider.INSTANCE, - STALE_ROUTING_TABLE_PURGE_DELAY_MS, - ignored -> {}); - - var handler = factory.newInstance(database("Molly"), null); - var table = handler.routingTable(); - - assertEquals("Molly", table.database().description()); - - assertEquals(0, table.routers().size()); - assertEquals(0, table.readers().size()); - assertEquals(0, table.writers().size()); - - assertTrue(table.isStaleFor(AccessMode.READ)); - assertTrue(table.isStaleFor(AccessMode.WRITE)); - } - - @ParameterizedTest - @ValueSource(strings = {SYSTEM_DATABASE_NAME, "", "database", " molly "}) - void shouldCreateRoutingTableHandlerIfAbsentWhenFreshRoutingTable(String databaseName) { - // Given - ConcurrentMap map = new ConcurrentHashMap<>(); - var factory = mockedHandlerFactory(); - var routingTables = newRoutingTables(map, factory); - - // When - var database = database(databaseName); - routingTables.ensureRoutingTable( - SecurityPlans.unencrypted(), - CompletableFuture.completedFuture(database), - AccessMode.READ, - Collections.emptySet(), - null, - () -> CompletableFuture.completedStage(AuthTokens.custom(Collections.emptyMap())), - new BoltProtocolVersion(4, 1), - null); - - // Then - assertTrue(map.containsKey(database)); - verify(factory).newInstance(eq(database), eq(routingTables)); - } - - @ParameterizedTest - @ValueSource(strings = {SYSTEM_DATABASE_NAME, "", "database", " molly "}) - void shouldReturnExistingRoutingTableHandlerWhenFreshRoutingTable(String databaseName) { - // Given - ConcurrentMap map = new ConcurrentHashMap<>(); - var handler = mockedRoutingTableHandler(); - var database = database(databaseName); - map.put(database, handler); - - var factory = mockedHandlerFactory(); - var routingTables = newRoutingTables(map, factory); - Supplier> authStageSupplier = - () -> CompletableFuture.completedStage(AuthTokens.custom(Collections.emptyMap())); - - // When - var actual = routingTables - .ensureRoutingTable( - SecurityPlans.unencrypted(), - CompletableFuture.completedFuture(database), - AccessMode.READ, - Collections.emptySet(), - null, - authStageSupplier, - new BoltProtocolVersion(4, 1), - null) - .toCompletableFuture() - .join(); - - // Then it is the one we put in map that is picked up. - verify(handler) - .ensureRoutingTable( - SecurityPlans.unencrypted(), - AccessMode.READ, - Collections.emptySet(), - authStageSupplier, - new BoltProtocolVersion(4, 1)); - // Then it is the one we put in map that is picked up. - assertEquals(handler, actual); - } - - @ParameterizedTest - @EnumSource(AccessMode.class) - void shouldReturnFreshRoutingTable(AccessMode mode) { - // Given - ConcurrentMap map = new ConcurrentHashMap<>(); - var handler = mockedRoutingTableHandler(); - var factory = mockedHandlerFactory(handler); - var routingTables = new RoutingTableRegistryImpl( - map, factory, null, null, Mockito.mock(Rediscovery.class), NoopLoggingProvider.INSTANCE); - Supplier> authStageSupplier = - () -> CompletableFuture.completedStage(AuthTokens.custom(Collections.emptyMap())); - - // When - routingTables - .ensureRoutingTable( - SecurityPlans.unencrypted(), - CompletableFuture.completedFuture(defaultDatabase()), - mode, - Collections.emptySet(), - null, - authStageSupplier, - new BoltProtocolVersion(4, 1), - null) - .toCompletableFuture() - .join(); - - // Then - verify(handler) - .ensureRoutingTable( - SecurityPlans.unencrypted(), - mode, - Collections.emptySet(), - authStageSupplier, - new BoltProtocolVersion(4, 1)); - } - - @Test - void shouldReturnServersInAllRoutingTables() { - // Given - ConcurrentMap map = new ConcurrentHashMap<>(); - map.put(database("Apple"), mockedRoutingTableHandler(A, B, C)); - map.put(database("Banana"), mockedRoutingTableHandler(B, C, D)); - map.put(database("Orange"), mockedRoutingTableHandler(E, F, C)); - var factory = mockedHandlerFactory(); - var routingTables = new RoutingTableRegistryImpl( - map, factory, null, null, Mockito.mock(Rediscovery.class), NoopLoggingProvider.INSTANCE); - - // When - var servers = routingTables.allServers(); - - // Then - assertEquals(Set.of(A, B, C, D, E, F), servers); - } - - @Test - void shouldRemoveRoutingTableHandler() { - // Given - ConcurrentMap map = new ConcurrentHashMap<>(); - map.put(database("Apple"), mockedRoutingTableHandler(A)); - map.put(database("Banana"), mockedRoutingTableHandler(B)); - map.put(database("Orange"), mockedRoutingTableHandler(C)); - - var factory = mockedHandlerFactory(); - var routingTables = newRoutingTables(map, factory); - - // When - routingTables.remove(database("Apple")); - routingTables.remove(database("Banana")); - // Then - assertTrue(routingTables.allServers().contains(C)); - } - - @Test - void shouldRemoveStaleRoutingTableHandlers() { - ConcurrentMap map = new ConcurrentHashMap<>(); - map.put(database("Apple"), mockedRoutingTableHandler(A)); - map.put(database("Banana"), mockedRoutingTableHandler(B)); - map.put(database("Orange"), mockedRoutingTableHandler(C)); - - var factory = mockedHandlerFactory(); - var routingTables = newRoutingTables(map, factory); - - // When - routingTables.removeAged(); - // Then - assertTrue(routingTables.allServers().isEmpty()); - } - - @Test - void shouldNotAcceptNullRediscovery() { - // GIVEN - var factory = mockedHandlerFactory(); - var clock = mock(Clock.class); - - // WHEN & THEN - assertThrows( - NullPointerException.class, - () -> new RoutingTableRegistryImpl( - new ConcurrentHashMap<>(), factory, clock, mock(), null, NoopLoggingProvider.INSTANCE)); - } - - private RoutingTableHandler mockedRoutingTableHandler(BoltServerAddress... servers) { - var handler = Mockito.mock(RoutingTableHandler.class); - when(handler.servers()).thenReturn(new HashSet<>(Arrays.asList(servers))); - when(handler.isRoutingTableAged()).thenReturn(true); - return handler; - } - - private RoutingTableRegistryImpl newRoutingTables( - ConcurrentMap handlers, - RoutingTableRegistryImpl.RoutingTableHandlerFactory factory) { - return new RoutingTableRegistryImpl( - handlers, factory, null, null, Mockito.mock(Rediscovery.class), NoopLoggingProvider.INSTANCE); - } - - private RoutingTableRegistryImpl.RoutingTableHandlerFactory mockedHandlerFactory(RoutingTableHandler handler) { - var factory = mock(RoutingTableRegistryImpl.RoutingTableHandlerFactory.class); - when(factory.newInstance(any(), any())).thenReturn(handler); - return factory; - } - - private RoutingTableRegistryImpl.RoutingTableHandlerFactory mockedHandlerFactory() { - return mockedHandlerFactory(mockedRoutingTableHandler()); - } - - private RoutingTableHandler mockedRoutingTableHandler() { - var handler = Mockito.mock(RoutingTableHandler.class); - when(handler.ensureRoutingTable(any(), any(), any(), any(), any())) - .thenReturn(completedFuture(Mockito.mock(RoutingTable.class))); - return handler; - } -} diff --git a/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/loadbalancing/LeastConnectedLoadBalancingStrategyTest.java b/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/loadbalancing/LeastConnectedLoadBalancingStrategyTest.java deleted file mode 100644 index 05d0c41ba5..0000000000 --- a/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/loadbalancing/LeastConnectedLoadBalancingStrategyTest.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl.cluster.loadbalancing; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.startsWith; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; -import static org.neo4j.driver.internal.bolt.routedimpl.impl.util.ClusterCompositionUtil.A; - -import java.util.Arrays; -import java.util.Collections; -import java.util.function.Function; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.routedimpl.impl.NoopLoggingProvider; - -class LeastConnectedLoadBalancingStrategyTest { - @Mock - private Function inUseFunction; - - private LeastConnectedLoadBalancingStrategy strategy; - - @BeforeEach - @SuppressWarnings("resource") - void setUp() { - openMocks(this); - strategy = new LeastConnectedLoadBalancingStrategy(inUseFunction, NoopLoggingProvider.INSTANCE); - given(inUseFunction.apply(any())).willReturn(0); - } - - @Test - void shouldHandleEmptyReaders() { - assertNull(strategy.selectReader(Collections.emptyList())); - } - - @Test - void shouldHandleEmptyWriters() { - assertNull(strategy.selectWriter(Collections.emptyList())); - } - - @Test - void shouldHandleSingleReaderWithoutActiveConnections() { - var address = new BoltServerAddress("reader", 9999); - - assertEquals(address, strategy.selectReader(Collections.singletonList(address))); - } - - @Test - void shouldHandleSingleWriterWithoutActiveConnections() { - var address = new BoltServerAddress("writer", 9999); - - assertEquals(address, strategy.selectWriter(Collections.singletonList(address))); - } - - @Test - void shouldHandleSingleReaderWithActiveConnections() { - var address = new BoltServerAddress("reader", 9999); - when(inUseFunction.apply(address)).thenReturn(42); - - assertEquals(address, strategy.selectReader(Collections.singletonList(address))); - } - - @Test - void shouldHandleSingleWriterWithActiveConnections() { - var address = new BoltServerAddress("writer", 9999); - when(inUseFunction.apply(address)).thenReturn(24); - - assertEquals(address, strategy.selectWriter(Collections.singletonList(address))); - } - - @Test - void shouldHandleMultipleReadersWithActiveConnections() { - var address1 = new BoltServerAddress("reader", 1); - var address2 = new BoltServerAddress("reader", 2); - var address3 = new BoltServerAddress("reader", 3); - - when(inUseFunction.apply(address1)).thenReturn(3); - when(inUseFunction.apply(address2)).thenReturn(4); - when(inUseFunction.apply(address3)).thenReturn(1); - - assertEquals(address3, strategy.selectReader(Arrays.asList(address1, address2, address3))); - } - - @Test - void shouldHandleMultipleWritersWithActiveConnections() { - var address1 = new BoltServerAddress("writer", 1); - var address2 = new BoltServerAddress("writer", 2); - var address3 = new BoltServerAddress("writer", 3); - var address4 = new BoltServerAddress("writer", 4); - - when(inUseFunction.apply(address1)).thenReturn(5); - when(inUseFunction.apply(address2)).thenReturn(6); - when(inUseFunction.apply(address3)).thenReturn(0); - when(inUseFunction.apply(address4)).thenReturn(1); - - assertEquals(address3, strategy.selectWriter(Arrays.asList(address1, address2, address3, address4))); - } - - @Test - void shouldReturnDifferentReaderOnEveryInvocationWhenNoActiveConnections() { - var address1 = new BoltServerAddress("reader", 1); - var address2 = new BoltServerAddress("reader", 2); - var address3 = new BoltServerAddress("reader", 3); - - assertEquals(address1, strategy.selectReader(Arrays.asList(address1, address2, address3))); - assertEquals(address2, strategy.selectReader(Arrays.asList(address1, address2, address3))); - assertEquals(address3, strategy.selectReader(Arrays.asList(address1, address2, address3))); - - assertEquals(address1, strategy.selectReader(Arrays.asList(address1, address2, address3))); - assertEquals(address2, strategy.selectReader(Arrays.asList(address1, address2, address3))); - assertEquals(address3, strategy.selectReader(Arrays.asList(address1, address2, address3))); - } - - @Test - void shouldReturnDifferentWriterOnEveryInvocationWhenNoActiveConnections() { - var address1 = new BoltServerAddress("writer", 1); - var address2 = new BoltServerAddress("writer", 2); - - assertEquals(address1, strategy.selectReader(Arrays.asList(address1, address2))); - assertEquals(address2, strategy.selectReader(Arrays.asList(address1, address2))); - - assertEquals(address1, strategy.selectReader(Arrays.asList(address1, address2))); - assertEquals(address2, strategy.selectReader(Arrays.asList(address1, address2))); - } - - @Test - void shouldTraceLogWhenNoAddressSelected() { - var logging = mock(LoggingProvider.class); - var logger = mock(System.Logger.class); - when(logging.getLog(any(Class.class))).thenReturn(logger); - - LoadBalancingStrategy strategy = new LeastConnectedLoadBalancingStrategy(inUseFunction, logging); - - strategy.selectReader(Collections.emptyList()); - strategy.selectWriter(Collections.emptyList()); - - verify(logger).log(eq(System.Logger.Level.TRACE), startsWith("Unable to select"), eq("reader")); - verify(logger).log(eq(System.Logger.Level.TRACE), startsWith("Unable to select"), eq("writer")); - } - - @Test - void shouldTraceLogSelectedAddress() { - var logging = mock(LoggingProvider.class); - var logger = mock(System.Logger.class); - when(logging.getLog(any(Class.class))).thenReturn(logger); - - when(inUseFunction.apply(any(BoltServerAddress.class))).thenReturn(42); - - LoadBalancingStrategy strategy = new LeastConnectedLoadBalancingStrategy(inUseFunction, logging); - - strategy.selectReader(Collections.singletonList(A)); - strategy.selectWriter(Collections.singletonList(A)); - - verify(logger).log(eq(System.Logger.Level.TRACE), startsWith("Selected"), eq("reader"), eq(A), eq(42)); - verify(logger).log(eq(System.Logger.Level.TRACE), startsWith("Selected"), eq("writer"), eq(A), eq(42)); - } -} diff --git a/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/loadbalancing/RoundRobinArrayIndexTest.java b/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/loadbalancing/RoundRobinArrayIndexTest.java deleted file mode 100644 index e06da1ab98..0000000000 --- a/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/cluster/loadbalancing/RoundRobinArrayIndexTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl.cluster.loadbalancing; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.junit.jupiter.api.Test; - -class RoundRobinArrayIndexTest { - @Test - void shouldHandleZeroLength() { - var roundRobinIndex = new RoundRobinArrayIndex(); - - var index = roundRobinIndex.next(0); - - assertEquals(-1, index); - } - - @Test - void shouldReturnIndexesInRoundRobinOrder() { - var roundRobinIndex = new RoundRobinArrayIndex(); - - for (var i = 0; i < 10; i++) { - var index = roundRobinIndex.next(10); - assertEquals(i, index); - } - - for (var i = 0; i < 5; i++) { - var index = roundRobinIndex.next(5); - assertEquals(i, index); - } - } - - @Test - void shouldHandleOverflow() { - var arrayLength = 10; - var roundRobinIndex = new RoundRobinArrayIndex(Integer.MAX_VALUE - 1); - - assertEquals((Integer.MAX_VALUE - 1) % arrayLength, roundRobinIndex.next(arrayLength)); - assertEquals(Integer.MAX_VALUE % arrayLength, roundRobinIndex.next(arrayLength)); - assertEquals(0, roundRobinIndex.next(arrayLength)); - assertEquals(1, roundRobinIndex.next(arrayLength)); - assertEquals(2, roundRobinIndex.next(arrayLength)); - } -} diff --git a/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/util/ClusterCompositionUtil.java b/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/util/ClusterCompositionUtil.java deleted file mode 100644 index fda67a9625..0000000000 --- a/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/util/ClusterCompositionUtil.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl.util; - -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.ClusterComposition; - -public final class ClusterCompositionUtil { - private ClusterCompositionUtil() {} - - public static final long NEVER_EXPIRE = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1); - - public static final BoltServerAddress A = new BoltServerAddress("192.168.100.100:11"); - public static final BoltServerAddress B = new BoltServerAddress("192.168.100.101:22"); - public static final BoltServerAddress C = new BoltServerAddress("192.168.100.102:33"); - public static final BoltServerAddress D = new BoltServerAddress("192.168.100.103:44"); - public static final BoltServerAddress E = new BoltServerAddress("192.168.100.104:55"); - public static final BoltServerAddress F = new BoltServerAddress("192.168.100.105:66"); - - public static final List EMPTY = new ArrayList<>(); - - @SafeVarargs - public static ClusterComposition createClusterComposition(List... servers) { - return createClusterComposition(NEVER_EXPIRE, servers); - } - - @SafeVarargs - @SuppressWarnings("fallthrough") - public static ClusterComposition createClusterComposition( - long expirationTimestamp, List... servers) { - Set routers = new LinkedHashSet<>(); - Set writers = new LinkedHashSet<>(); - Set readers = new LinkedHashSet<>(); - - switch (servers.length) { - case 3: - readers.addAll(servers[2]); - // no break on purpose - case 2: - writers.addAll(servers[1]); - // no break on purpose - case 1: - routers.addAll(servers[0]); - } - return new ClusterComposition(expirationTimestamp, readers, writers, routers, null); - } -} diff --git a/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/util/FakeClock.java b/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/util/FakeClock.java deleted file mode 100644 index df250f46a8..0000000000 --- a/bolt-api-routed/src/test/java/org/neo4j/driver/internal/bolt/routedimpl/impl/util/FakeClock.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.routedimpl.impl.util; - -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneId; -import java.util.concurrent.atomic.AtomicLong; - -public class FakeClock extends Clock { - private final AtomicLong timestamp = new AtomicLong(); - - @Override - public ZoneId getZone() { - throw new UnsupportedOperationException(); - } - - @Override - public Clock withZone(ZoneId zone) { - throw new UnsupportedOperationException(); - } - - @Override - public Instant instant() { - return Instant.ofEpochMilli(timestamp.get()); - } - - public void progress(long millis) { - if (millis < 0) { - throw new IllegalArgumentException("time can only progress forwards"); - } - timestamp.addAndGet(millis); - } -} diff --git a/bolt-api-test-values/LICENSES.txt b/bolt-api-test-values/LICENSES.txt deleted file mode 100644 index f8e0fd3292..0000000000 --- a/bolt-api-test-values/LICENSES.txt +++ /dev/null @@ -1,5 +0,0 @@ -This file contains the full license text of the included third party -libraries. For an overview of the licenses see the NOTICE.txt file. - - - diff --git a/bolt-api-test-values/NOTICE.txt b/bolt-api-test-values/NOTICE.txt deleted file mode 100644 index c3bf48c6fc..0000000000 --- a/bolt-api-test-values/NOTICE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) "Neo4j" -Neo4j Sweden AB [https://neo4j.com] - -This file is part of Neo4j. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -Full license texts are found in LICENSES.txt. - - -Third-party licenses --------------------- - diff --git a/bolt-api-test-values/pom.xml b/bolt-api-test-values/pom.xml deleted file mode 100644 index 35c422959b..0000000000 --- a/bolt-api-test-values/pom.xml +++ /dev/null @@ -1,70 +0,0 @@ - - 4.0.0 - - - org.neo4j.driver - neo4j-java-driver-parent - 5.28-SNAPSHOT - - - neo4j-bolt-api-test-values - - jar - Neo4j Bolt API - https://github.com/neo4j/neo4j-java-driver - - - ${project.basedir}/.. - ,-try - - - - - org.neo4j.driver - neo4j-bolt-api - ${project.version} - - - - org.mockito - mockito-core - - - org.junit.jupiter - junit-jupiter - - - - - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-javadoc-plugin - - - org.apache.maven.plugins - maven-failsafe-plugin - - - org.apache.maven.surefire - surefire-junit-platform - ${surefire.and.failsafe.version} - - - - - - - - scm:git:git://github.com/neo4j/neo4j-java-driver.git - scm:git:git@github.com:neo4j/neo4j-java-driver.git - https://github.com/neo4j/neo4j-java-driver - - - diff --git a/bolt-api-test-values/src/main/java/module-info.java b/bolt-api-test-values/src/main/java/module-info.java deleted file mode 100644 index 7a8207ce82..0000000000 --- a/bolt-api-test-values/src/main/java/module-info.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -module org.neo4j.bolt.netty.test.values { - requires transitive org.neo4j.bolt.api; -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/TestNode.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/TestNode.java deleted file mode 100644 index 80a58ae74b..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/TestNode.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values; - -import org.neo4j.bolt.api.test.values.impl.Entity; -import org.neo4j.driver.internal.bolt.api.values.Node; - -public interface TestNode extends Entity, Node { - - Iterable labels(); - - boolean hasLabel(String label); -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/TestPath.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/TestPath.java deleted file mode 100644 index 88dd1a472e..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/TestPath.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values; - -import org.neo4j.driver.internal.bolt.api.values.Path; -import org.neo4j.driver.internal.bolt.api.values.Segment; - -public interface TestPath extends Iterable, Path { - interface TestSegment extends Segment { - TestRelationship relationship(); - - TestNode start(); - - TestNode end(); - } - - TestNode start(); - - TestNode end(); - - int length(); - - boolean contains(TestNode node); - - boolean contains(TestRelationship relationship); - - Iterable nodes(); - - Iterable relationships(); -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/TestRelationship.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/TestRelationship.java deleted file mode 100644 index 8c5614a893..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/TestRelationship.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values; - -import org.neo4j.bolt.api.test.values.impl.Entity; -import org.neo4j.driver.internal.bolt.api.values.Relationship; - -public interface TestRelationship extends Entity, Relationship { - - long startNodeId(); - - String startNodeElementId(); - - long endNodeId(); - - String endNodeElementId(); - - String typeString(); -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/TestValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/TestValue.java deleted file mode 100644 index 429b0e4961..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/TestValue.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values; - -import org.neo4j.bolt.api.test.values.impl.AsValue; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public interface TestValue extends Value, AsValue { - TestNode asNode(); - - TestRelationship asRelationship(); - - TestPath asPath(); -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/TestValueFactory.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/TestValueFactory.java deleted file mode 100644 index e639669cc4..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/TestValueFactory.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values; - -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; - -import java.time.DateTimeException; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.neo4j.bolt.api.test.values.impl.InternalNode; -import org.neo4j.bolt.api.test.values.impl.InternalPath; -import org.neo4j.bolt.api.test.values.impl.InternalRelationship; -import org.neo4j.bolt.api.test.values.impl.NodeValue; -import org.neo4j.bolt.api.test.values.impl.PathValue; -import org.neo4j.bolt.api.test.values.impl.RelationshipValue; -import org.neo4j.bolt.api.test.values.impl.UnsupportedDateTimeValue; -import org.neo4j.driver.internal.bolt.api.values.Node; -import org.neo4j.driver.internal.bolt.api.values.Path; -import org.neo4j.driver.internal.bolt.api.values.Relationship; -import org.neo4j.driver.internal.bolt.api.values.Segment; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; - -public class TestValueFactory implements ValueFactory { - public static final TestValueFactory INSTANCE = new TestValueFactory(); - - private TestValueFactory() {} - - @Override - public Value value(Object value) { - return Values.value(value); - } - - @Override - public Node node(long id, String elementId, Collection labels, Map properties) { - return new InternalNode(id, elementId, labels, properties); - } - - @Override - public Relationship relationship( - long id, - String elementId, - long start, - String startElementId, - long end, - String endElementId, - String type, - Map properties) { - return new InternalRelationship(id, elementId, start, startElementId, end, endElementId, type, properties); - } - - @Override - public Segment segment(Node start, Relationship relationship, Node end) { - return new InternalPath.SelfContainedSegment((TestNode) start, (TestRelationship) relationship, (TestNode) end); - } - - @Override - public Path path(List segments, List nodes, List relationships) { - return new InternalPath( - segments.stream().map(TestPath.TestSegment.class::cast).toList(), - nodes.stream().map(TestNode.class::cast).toList(), - relationships.stream().map(TestRelationship.class::cast).toList()); - } - - @Override - public Value isoDuration(long months, long days, long seconds, int nanoseconds) { - return Values.isoDuration(months, days, seconds, nanoseconds); - } - - @Override - public Value point(int srid, double x, double y) { - return Values.point(srid, x, y); - } - - @Override - public Value point(int srid, double x, double y, double z) { - return Values.point(srid, x, y, z); - } - - @Override - public Value unsupportedDateTimeValue(DateTimeException e) { - return new UnsupportedDateTimeValue(e); - } - - public Value emptyNodeValue() { - return new NodeValue(new InternalNode(1234, singletonList("User"), new HashMap<>())); - } - - public Value filledNodeValue() { - return new NodeValue(new InternalNode(1234, singletonList("User"), singletonMap("name", value("Dodo")))); - } - - public Value emptyRelationshipValue() { - return new RelationshipValue(new InternalRelationship(1234, 1, 2, "KNOWS")); - } - - public Value filledRelationshipValue() { - return new RelationshipValue( - new InternalRelationship(1234, 1, 2, "KNOWS", singletonMap("name", value("Dodo")))); - } - - public Value filledPathValue() { - return new PathValue(new InternalPath( - new InternalNode(42L), new InternalRelationship(43L, 42L, 44L, "T"), new InternalNode(44L))); - } - - public Value emptyPathValue() { - return new PathValue(new InternalPath(new InternalNode(1))); - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/Values.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/Values.java deleted file mode 100644 index 9a2f740ec3..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/Values.java +++ /dev/null @@ -1,579 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values; - -import java.time.Duration; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetDateTime; -import java.time.OffsetTime; -import java.time.Period; -import java.time.ZonedDateTime; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.stream.IntStream; -import java.util.stream.Stream; -import org.neo4j.bolt.api.test.values.impl.AsValue; -import org.neo4j.bolt.api.test.values.impl.BooleanValue; -import org.neo4j.bolt.api.test.values.impl.BytesValue; -import org.neo4j.bolt.api.test.values.impl.DateTimeValue; -import org.neo4j.bolt.api.test.values.impl.DateValue; -import org.neo4j.bolt.api.test.values.impl.DurationValue; -import org.neo4j.bolt.api.test.values.impl.FloatValue; -import org.neo4j.bolt.api.test.values.impl.IntegerValue; -import org.neo4j.bolt.api.test.values.impl.InternalIsoDuration; -import org.neo4j.bolt.api.test.values.impl.InternalPoint2D; -import org.neo4j.bolt.api.test.values.impl.InternalPoint3D; -import org.neo4j.bolt.api.test.values.impl.ListValue; -import org.neo4j.bolt.api.test.values.impl.LocalDateTimeValue; -import org.neo4j.bolt.api.test.values.impl.LocalTimeValue; -import org.neo4j.bolt.api.test.values.impl.MapValue; -import org.neo4j.bolt.api.test.values.impl.NullValue; -import org.neo4j.bolt.api.test.values.impl.PointValue; -import org.neo4j.bolt.api.test.values.impl.StringValue; -import org.neo4j.bolt.api.test.values.impl.TimeValue; -import org.neo4j.driver.internal.bolt.api.values.IsoDuration; -import org.neo4j.driver.internal.bolt.api.values.Point; -import org.neo4j.driver.internal.bolt.api.values.Value; - -final class Values { - public static final Value EmptyMap = value(Collections.emptyMap()); - - private Values() { - throw new UnsupportedOperationException(); - } - - /** - * Returns a value from object. - * - * @param value the object value - * @return the array of values - */ - @SuppressWarnings("unchecked") - public static Value value(Object value) { - if (value == null) { - return NullValue.NULL; - } - - if (value instanceof AsValue) { - return ((AsValue) value).asValue(); - } - if (value instanceof Boolean) { - return value((boolean) value); - } - if (value instanceof String) { - return value((String) value); - } - if (value instanceof Character) { - return value((char) value); - } - if (value instanceof Long) { - return value((long) value); - } - if (value instanceof Short) { - return value((short) value); - } - if (value instanceof Byte) { - return value((byte) value); - } - if (value instanceof Integer) { - return value((int) value); - } - if (value instanceof Double) { - return value((double) value); - } - if (value instanceof Float) { - return value((float) value); - } - if (value instanceof LocalDate) { - return value((LocalDate) value); - } - if (value instanceof OffsetTime) { - return value((OffsetTime) value); - } - if (value instanceof LocalTime) { - return value((LocalTime) value); - } - if (value instanceof LocalDateTime) { - return value((LocalDateTime) value); - } - if (value instanceof OffsetDateTime) { - return value((OffsetDateTime) value); - } - if (value instanceof ZonedDateTime) { - return value((ZonedDateTime) value); - } - if (value instanceof IsoDuration) { - return value((IsoDuration) value); - } - if (value instanceof Period) { - return value((Period) value); - } - if (value instanceof Duration) { - return value((Duration) value); - } - if (value instanceof Point) { - return value((Point) value); - } - - if (value instanceof List) { - return value((List) value); - } - if (value instanceof Map) { - return value((Map) value); - } - if (value instanceof Iterable) { - return value((Iterable) value); - } - if (value instanceof Iterator) { - return value((Iterator) value); - } - if (value instanceof Stream) { - return value((Stream) value); - } - - if (value instanceof char[]) { - return value((char[]) value); - } - if (value instanceof byte[]) { - return value((byte[]) value); - } - if (value instanceof boolean[]) { - return value((boolean[]) value); - } - if (value instanceof String[]) { - return value((String[]) value); - } - if (value instanceof long[]) { - return value((long[]) value); - } - if (value instanceof int[]) { - return value((int[]) value); - } - if (value instanceof short[]) { - return value((short[]) value); - } - if (value instanceof double[]) { - return value((double[]) value); - } - if (value instanceof float[]) { - return value((float[]) value); - } - if (value instanceof Value[]) { - return value((Value[]) value); - } - if (value instanceof Object[]) { - return value(Arrays.asList((Object[]) value)); - } - - throw new IllegalArgumentException( - "Unsupported value type: " + value.getClass().getName()); - } - - /** - * Returns an array of values from object vararg. - * - * @param input the object value(s) - * @return the array of values - */ - public static Value[] values(final Object... input) { - return Arrays.stream(input).map(Values::value).toArray(Value[]::new); - } - - /** - * Returns a value from value vararg. - * - * @param input the value(s) - * @return the value - */ - public static Value value(Value... input) { - var size = input.length; - var values = new Value[size]; - System.arraycopy(input, 0, values, 0, size); - return new ListValue(values); - } - - /** - * Returns a value from byte vararg. - * - * @param input the byte value(s) - * @return the value - */ - public static Value value(byte... input) { - return new BytesValue(input); - } - - /** - * Returns a value from string vararg. - * - * @param input the string value(s) - * @return the value - */ - public static Value value(String... input) { - var values = Arrays.stream(input).map(StringValue::new).toArray(StringValue[]::new); - return new ListValue(values); - } - - /** - * Returns a value from boolean vararg. - * - * @param input the boolean value(s) - * @return the value - */ - public static Value value(boolean... input) { - var values = - IntStream.range(0, input.length).mapToObj(i -> value(input[i])).toArray(Value[]::new); - return new ListValue(values); - } - - /** - * Returns a value from char vararg. - * - * @param input the char value(s) - * @return the value - */ - public static Value value(char... input) { - var values = - IntStream.range(0, input.length).mapToObj(i -> value(input[i])).toArray(Value[]::new); - return new ListValue(values); - } - - /** - * Returns a value from long vararg. - * - * @param input the long value(s) - * @return the value - */ - public static Value value(long... input) { - var values = Arrays.stream(input).mapToObj(Values::value).toArray(Value[]::new); - return new ListValue(values); - } - - /** - * Returns a value from short vararg. - * - * @param input the short value(s) - * @return the value - */ - public static Value value(short... input) { - var values = - IntStream.range(0, input.length).mapToObj(i -> value(input[i])).toArray(Value[]::new); - return new ListValue(values); - } - - /** - * Returns a value from int vararg. - * - * @param input the int value(s) - * @return the value - */ - public static Value value(int... input) { - var values = Arrays.stream(input).mapToObj(Values::value).toArray(Value[]::new); - return new ListValue(values); - } - - /** - * Returns a value from double vararg. - * - * @param input the double value(s) - * @return the value - */ - public static Value value(double... input) { - var values = Arrays.stream(input).mapToObj(Values::value).toArray(Value[]::new); - return new ListValue(values); - } - - /** - * Returns a value from float vararg. - * - * @param input the float value(s) - * @return the value - */ - public static Value value(float... input) { - var values = - IntStream.range(0, input.length).mapToObj(i -> value(input[i])).toArray(Value[]::new); - return new ListValue(values); - } - - /** - * Returns a value from list of objects. - * - * @param vals the list of objects - * @return the value - */ - public static Value value(List vals) { - var values = new Value[vals.size()]; - var i = 0; - for (var val : vals) { - values[i++] = value(val); - } - return new ListValue(values); - } - - /** - * Returns a value from iterable of objects. - * - * @param val the iterable of objects - * @return the value - */ - public static Value value(Iterable val) { - return value(val.iterator()); - } - - /** - * Returns a value from iterator of objects. - * - * @param val the iterator of objects - * @return the value - */ - public static Value value(Iterator val) { - List values = new ArrayList<>(); - while (val.hasNext()) { - values.add(value(val.next())); - } - return new ListValue(values.toArray(new Value[0])); - } - - /** - * Returns a value from stream of objects. - * - * @param stream the stream of objects - * @return the value - */ - public static Value value(Stream stream) { - var values = stream.map(Values::value).toArray(Value[]::new); - return new ListValue(values); - } - - /** - * Returns a value from char. - * - * @param val the char value - * @return the value - */ - public static Value value(final char val) { - return new StringValue(String.valueOf(val)); - } - - /** - * Returns a value from string. - * - * @param val the string value - * @return the value - */ - public static Value value(final String val) { - return new StringValue(val); - } - - /** - * Returns a value from long. - * - * @param val the long value - * @return the value - */ - public static Value value(final long val) { - return new IntegerValue(val); - } - - /** - * Returns a value from int. - * - * @param val the int value - * @return the value - */ - public static Value value(final int val) { - return new IntegerValue(val); - } - - /** - * Returns a value from double. - * - * @param val the double value - * @return the value - */ - public static Value value(final double val) { - return new FloatValue(val); - } - - /** - * Returns a value from boolean. - * - * @param val the boolean value - * @return the value - */ - public static Value value(final boolean val) { - return BooleanValue.fromBoolean(val); - } - - /** - * Returns a value from string to object map. - * - * @param val the string to object map - * @return the value - */ - public static Value value(final Map val) { - Map asValues = new HashMap<>(val.size()); - for (var entry : val.entrySet()) { - asValues.put(entry.getKey(), value(entry.getValue())); - } - return new MapValue(asValues); - } - - /** - * Returns a value from local date. - * - * @param localDate the local date value - * @return the value - */ - public static Value value(LocalDate localDate) { - return new DateValue(localDate); - } - - /** - * Returns a value from offset time. - * - * @param offsetTime the offset time value - * @return the value - */ - public static Value value(OffsetTime offsetTime) { - return new TimeValue(offsetTime); - } - - /** - * Returns a value from local time. - * - * @param localTime the local time value - * @return the value - */ - public static Value value(LocalTime localTime) { - return new LocalTimeValue(localTime); - } - - /** - * Returns a value from local date time. - * - * @param localDateTime the local date time value - * @return the value - */ - public static Value value(LocalDateTime localDateTime) { - return new LocalDateTimeValue(localDateTime); - } - - /** - * Returns a value from offset date time. - * - * @param offsetDateTime the offset date time value - * @return the value - */ - public static Value value(OffsetDateTime offsetDateTime) { - return new DateTimeValue(offsetDateTime.toZonedDateTime()); - } - - /** - * Returns a value from zoned date time. - * - * @param zonedDateTime the zoned date time value - * @return the value - */ - public static Value value(ZonedDateTime zonedDateTime) { - return new DateTimeValue(zonedDateTime); - } - - /** - * Returns a value from period. - * - * @param period the period value - * @return the value - */ - public static Value value(Period period) { - return value(new InternalIsoDuration(period)); - } - - /** - * Returns a value from duration. - * - * @param duration the duration value - * @return the value - */ - public static Value value(Duration duration) { - return value(new InternalIsoDuration(duration)); - } - - /** - * Returns a value from month, day, seconds and nanoseconds values. - * - * @param months the month value - * @param days the day value - * @param seconds the seconds value - * @param nanoseconds the nanoseconds value - * @return the value - */ - public static Value isoDuration(long months, long days, long seconds, int nanoseconds) { - return value(new InternalIsoDuration(months, days, seconds, nanoseconds)); - } - - /** - * Returns a value from ISO duration. - * - * @param duration the ISO duration value - * @return the value - */ - private static Value value(IsoDuration duration) { - return new DurationValue(duration); - } - - /** - * Returns a value from SRID, x and y values. - * - * @param srid the SRID value - * @param x the x value - * @param y the y value - * @return the value - */ - public static Value point(int srid, double x, double y) { - return value(new InternalPoint2D(srid, x, y)); - } - - /** - * Returns a value from point. - * - * @param point the point value - * @return the value - */ - private static Value value(Point point) { - return new PointValue(point); - } - - /** - * Returns a value from SRID, x ,y and z values. - * - * @param srid the SRID value - * @param x the x value - * @param y the y value - * @param z the z value - * @return the value - */ - public static Value point(int srid, double x, double y, double z) { - return value(new InternalPoint3D(srid, x, y, z)); - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/AsValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/AsValue.java deleted file mode 100644 index 003eb35457..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/AsValue.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import org.neo4j.driver.internal.bolt.api.values.Value; - -public interface AsValue { - Value asValue(); -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/BooleanValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/BooleanValue.java deleted file mode 100644 index a349ed2c9f..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/BooleanValue.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import org.neo4j.driver.internal.bolt.api.values.Type; - -public abstract class BooleanValue extends ValueAdapter { - private BooleanValue() { - // do nothing - } - - public static final BooleanValue TRUE = new TrueValue(); - public static final BooleanValue FALSE = new FalseValue(); - - public static BooleanValue fromBoolean(boolean value) { - return value ? TRUE : FALSE; - } - - @Override - public Type type() { - return Type.BOOLEAN; - } - - @Override - public int hashCode() { - var value = asBoolean() ? Boolean.TRUE : Boolean.FALSE; - return value.hashCode(); - } - - private static class TrueValue extends BooleanValue { - @Override - public boolean asBoolean() { - return true; - } - - @SuppressWarnings("EqualsWhichDoesntCheckParameterClass") - @Override - public boolean equals(Object obj) { - return obj == TRUE; - } - - @Override - public String toString() { - return "TRUE"; - } - } - - private static class FalseValue extends BooleanValue { - @Override - public boolean asBoolean() { - return false; - } - - @SuppressWarnings("EqualsWhichDoesntCheckParameterClass") - @Override - public boolean equals(Object obj) { - return obj == FALSE; - } - - @Override - public String toString() { - return "FALSE"; - } - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/BytesValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/BytesValue.java deleted file mode 100644 index 3f2c4f22cd..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/BytesValue.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import java.util.Arrays; -import org.neo4j.driver.internal.bolt.api.values.Type; - -public class BytesValue extends ValueAdapter { - private final byte[] val; - - public BytesValue(byte[] val) { - if (val == null) { - throw new IllegalArgumentException("Cannot construct BytesValue from null"); - } - this.val = val; - } - - @Override - public boolean isEmpty() { - return val.length == 0; - } - - @Override - public int size() { - return val.length; - } - - @Override - public byte[] asByteArray() { - return val; - } - - @Override - public Type type() { - return Type.BYTES; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - var values = (BytesValue) o; - return Arrays.equals(val, values.val); - } - - @Override - public int hashCode() { - return Arrays.hashCode(val); - } - - @Override - public String toString() { - var s = new StringBuilder("#"); - for (var b : val) { - if (b < 0x10) { - s.append('0'); - } - s.append(Integer.toHexString(b)); - } - return s.toString(); - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/DateTimeValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/DateTimeValue.java deleted file mode 100644 index 32f054a52c..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/DateTimeValue.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import java.time.ZonedDateTime; -import org.neo4j.driver.internal.bolt.api.values.Type; - -public class DateTimeValue extends ObjectValueAdapter { - public DateTimeValue(ZonedDateTime zonedDateTime) { - super(zonedDateTime); - } - - @Override - public ZonedDateTime asZonedDateTime() { - return asObject(); - } - - @Override - public Type type() { - return Type.DATE_TIME; - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/DateValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/DateValue.java deleted file mode 100644 index f147b668f0..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/DateValue.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import java.time.LocalDate; -import org.neo4j.driver.internal.bolt.api.values.Type; - -public class DateValue extends ObjectValueAdapter { - public DateValue(LocalDate date) { - super(date); - } - - @Override - public LocalDate asLocalDate() { - return asObject(); - } - - @Override - public Type type() { - return Type.DATE; - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/DurationValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/DurationValue.java deleted file mode 100644 index bf683eec4b..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/DurationValue.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import org.neo4j.driver.internal.bolt.api.values.IsoDuration; -import org.neo4j.driver.internal.bolt.api.values.Type; - -public class DurationValue extends ObjectValueAdapter { - public DurationValue(IsoDuration duration) { - super(duration); - } - - @Override - public IsoDuration asIsoDuration() { - return asObject(); - } - - @Override - public Type type() { - return Type.DURATION; - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/Entity.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/Entity.java deleted file mode 100644 index ad241ef4ed..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/Entity.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import java.util.Map; -import java.util.function.Function; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public interface Entity { - - long id(); - - String elementId(); - - Iterable keys(); - - Value get(String key); - - int size(); - - Map asMap(Function mapFunction); -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/EntityValueAdapter.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/EntityValueAdapter.java deleted file mode 100644 index 88f97762eb..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/EntityValueAdapter.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import java.util.Map; -import java.util.function.Function; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public abstract class EntityValueAdapter extends ObjectValueAdapter { - protected EntityValueAdapter(V adapted) { - super(adapted); - } - - public V asEntity() { - return asObject(); - } - - @Override - public Map asMap(Function mapFunction) { - return asEntity().asMap(mapFunction); - } - - @Override - public int size() { - return asEntity().size(); - } - - @Override - public Iterable keys() { - return asEntity().keys(); - } - - @Override - public Value get(String key) { - return asEntity().get(key); - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/Extract.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/Extract.java deleted file mode 100644 index 5ce5f50efb..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/Extract.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; -import static java.util.Collections.unmodifiableMap; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.function.Function; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public final class Extract { - private Extract() { - throw new UnsupportedOperationException(); - } - - public static Map map(Map data, Function mapFunction) { - if (data.isEmpty()) { - return emptyMap(); - } else { - var size = data.size(); - if (size == 1) { - var head = data.entrySet().iterator().next(); - return singletonMap(head.getKey(), mapFunction.apply(head.getValue())); - } else { - Map map = new LinkedHashMap<>(size); - for (var entry : data.entrySet()) { - map.put(entry.getKey(), mapFunction.apply(entry.getValue())); - } - return unmodifiableMap(map); - } - } - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/FloatValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/FloatValue.java deleted file mode 100644 index 50ad171aa8..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/FloatValue.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import org.neo4j.driver.internal.bolt.api.values.Type; - -public class FloatValue extends NumberValueAdapter { - private final double val; - - public FloatValue(double val) { - this.val = val; - } - - @Override - public Type type() { - return Type.FLOAT; - } - - @Override - public Double asNumber() { - return val; - } - - @Override - public long asLong() { - var longVal = (long) val; - if ((double) longVal != val) { - throw new LossyCoercion(type().name(), "Java long"); - } - - return longVal; - } - - @Override - public double asDouble() { - return val; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - var values = (FloatValue) o; - return Double.compare(values.val, val) == 0; - } - - @Override - public int hashCode() { - var temp = Double.doubleToLongBits(val); - return (int) (temp ^ (temp >>> 32)); - } - - @Override - public String toString() { - return Double.toString(val); - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/IntegerValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/IntegerValue.java deleted file mode 100644 index c4f1bfc9bc..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/IntegerValue.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import org.neo4j.driver.internal.bolt.api.values.Type; - -public class IntegerValue extends NumberValueAdapter { - private final long val; - - public IntegerValue(long val) { - this.val = val; - } - - @Override - public Type type() { - return Type.INTEGER; - } - - @Override - public Long asNumber() { - return val; - } - - @Override - public long asLong() { - return val; - } - - @Override - public double asDouble() { - var doubleVal = (double) val; - if ((long) doubleVal != val) { - throw new LossyCoercion(type().name(), "Java double"); - } - - return (double) val; - } - - @Override - public String toString() { - return Long.toString(val); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - var values = (IntegerValue) o; - return val == values.val; - } - - @Override - public int hashCode() { - return (int) (val ^ (val >>> 32)); - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalEntity.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalEntity.java deleted file mode 100644 index f8cfc33037..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalEntity.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import java.util.Map; -import java.util.function.Function; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public abstract class InternalEntity implements Entity, AsValue { - private final long id; - private final String elementId; - private final Map properties; - - public InternalEntity(long id, String elementId, Map properties) { - this.id = id; - this.elementId = elementId; - this.properties = properties; - } - - @Override - @Deprecated - public long id() { - return id; - } - - @Override - public String elementId() { - return elementId; - } - - @Override - public int size() { - return properties.size(); - } - - @Override - public Map asMap(Function mapFunction) { - return Extract.map(properties, mapFunction); - } - - @Override - public Iterable keys() { - return properties.keySet(); - } - - @Override - public Value get(String key) { - var value = properties.get(key); - return value == null ? NullValue.NULL : value; - } - - @Override - public Value asValue() { - return new MapValue(properties); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - var that = (InternalEntity) o; - - return id == that.id; - } - - @Override - public int hashCode() { - return (int) (id ^ (id >>> 32)); - } - - @Override - public String toString() { - return "Entity{" + "id=" + id + ", properties=" + properties + '}'; - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalIsoDuration.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalIsoDuration.java deleted file mode 100644 index a7acbfda0e..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalIsoDuration.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import static java.time.temporal.ChronoUnit.DAYS; -import static java.time.temporal.ChronoUnit.MONTHS; -import static java.time.temporal.ChronoUnit.NANOS; -import static java.time.temporal.ChronoUnit.SECONDS; - -import java.time.Duration; -import java.time.Period; -import java.time.temporal.TemporalUnit; -import java.util.List; -import java.util.Objects; -import org.neo4j.driver.internal.bolt.api.values.IsoDuration; - -public class InternalIsoDuration implements IsoDuration { - private static final long NANOS_PER_SECOND = 1_000_000_000; - private static final List SUPPORTED_UNITS = List.of(MONTHS, DAYS, SECONDS, NANOS); - - private final long months; - private final long days; - private final long seconds; - private final int nanoseconds; - - public InternalIsoDuration(Period period) { - this(period.toTotalMonths(), period.getDays(), Duration.ZERO); - } - - public InternalIsoDuration(Duration duration) { - this(0, 0, duration); - } - - public InternalIsoDuration(long months, long days, long seconds, int nanoseconds) { - this(months, days, Duration.ofSeconds(seconds, nanoseconds)); - } - - InternalIsoDuration(long months, long days, Duration duration) { - this.months = months; - this.days = days; - this.seconds = duration.getSeconds(); // normalized value of seconds - this.nanoseconds = duration.getNano(); // normalized value of nanoseconds in [0, 999_999_999] - } - - @Override - public long months() { - return months; - } - - @Override - public long days() { - return days; - } - - @Override - public long seconds() { - return seconds; - } - - @Override - public int nanoseconds() { - return nanoseconds; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - var that = (InternalIsoDuration) o; - return months == that.months && days == that.days && seconds == that.seconds && nanoseconds == that.nanoseconds; - } - - @Override - public int hashCode() { - return Objects.hash(months, days, seconds, nanoseconds); - } - - @Override - public String toString() { - var sb = new StringBuilder(); - sb.append('P'); - sb.append(months).append('M'); - sb.append(days).append('D'); - sb.append('T'); - if (seconds < 0 && nanoseconds > 0) { - if (seconds == -1) { - sb.append("-0"); - } else { - sb.append(seconds + 1); - } - } else { - sb.append(seconds); - } - if (nanoseconds > 0) { - var pos = sb.length(); - // append nanoseconds as a 10-digit string with leading '1' that is later replaced by a '.' - if (seconds < 0) { - sb.append(2 * NANOS_PER_SECOND - nanoseconds); - } else { - sb.append(NANOS_PER_SECOND + nanoseconds); - } - sb.setCharAt(pos, '.'); // replace '1' with '.' - } - sb.append('S'); - return sb.toString(); - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalMapAccessorWithDefaultValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalMapAccessorWithDefaultValue.java deleted file mode 100644 index 82b8570940..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalMapAccessorWithDefaultValue.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import org.neo4j.driver.internal.bolt.api.values.Value; - -public abstract class InternalMapAccessorWithDefaultValue implements Value { - public abstract Value get(String key); -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalNode.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalNode.java deleted file mode 100644 index 93ac4f78ab..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalNode.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import org.neo4j.bolt.api.test.values.TestNode; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public class InternalNode extends InternalEntity implements TestNode { - private final Collection labels; - - public InternalNode(long id) { - this(id, Collections.emptyList(), Collections.emptyMap()); - } - - public InternalNode(long id, Collection labels, Map properties) { - this(id, String.valueOf(id), labels, properties); - } - - public InternalNode(long id, String elementId, Collection labels, Map properties) { - super(id, elementId, properties); - this.labels = labels; - } - - @Override - public Collection labels() { - return labels; - } - - @Override - public boolean hasLabel(String label) { - return labels.contains(label); - } - - @Override - public Value asValue() { - return new NodeValue(this); - } - - @Override - @SuppressWarnings("deprecation") - public String toString() { - return String.format("node<%s>", id()); - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalPath.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalPath.java deleted file mode 100644 index c078d2eb14..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalPath.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import org.neo4j.bolt.api.test.values.TestNode; -import org.neo4j.bolt.api.test.values.TestPath; -import org.neo4j.bolt.api.test.values.TestRelationship; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public class InternalPath implements TestPath, AsValue { - public record SelfContainedSegment(TestNode start, TestRelationship relationship, TestNode end) - implements TestSegment { - - @Override - public boolean equals(Object other) { - if (this == other) { - return true; - } - if (other == null || getClass() != other.getClass()) { - return false; - } - - var that = (SelfContainedSegment) other; - return start.equals(that.start) && end.equals(that.end) && relationship.equals(that.relationship); - } - - @Override - public String toString() { - return String.format( - relationship.startNodeId() == start.id() ? "(%s)-[%s:%s]->(%s)" : "(%s)<-[%s:%s]-(%s)", - start.id(), - relationship.id(), - relationship.typeString(), - end.id()); - } - } - - private static boolean isEndpoint(TestNode node, TestRelationship relationship) { - return node.id() == relationship.startNodeId() || node.id() == relationship.endNodeId(); - } - - private final List nodes; - private final List relationships; - private final List segments; - - public InternalPath(List alternatingNodeAndRel) { - nodes = newList(alternatingNodeAndRel.size() / 2 + 1); - relationships = newList(alternatingNodeAndRel.size() / 2); - segments = newList(alternatingNodeAndRel.size() / 2); - - if (alternatingNodeAndRel.size() % 2 == 0) { - throw new IllegalArgumentException("An odd number of entities are required to build a path"); - } - TestNode lastNode = null; - TestRelationship lastRelationship = null; - var index = 0; - for (var entity : alternatingNodeAndRel) { - if (entity == null) { - throw new IllegalArgumentException("Path entities cannot be null"); - } - if (index % 2 == 0) { - // even index - this should be a node - try { - lastNode = (TestNode) entity; - if (nodes.isEmpty() || (lastRelationship != null && isEndpoint(lastNode, lastRelationship))) { - nodes.add(lastNode); - } else { - throw new IllegalArgumentException("Node argument " + index - + " is not an endpoint of relationship argument " + (index - 1)); - } - } catch (ClassCastException e) { - var cls = entity.getClass().getName(); - throw new IllegalArgumentException("Expected argument " + index + " to be a node " + index - + " but found a " + cls + " " + "instead"); - } - } else { - // odd index - this should be a relationship - try { - lastRelationship = (TestRelationship) entity; - if (isEndpoint(lastNode, lastRelationship)) { - relationships.add(lastRelationship); - } else { - throw new IllegalArgumentException("Node argument " + (index - 1) - + " is not an endpoint of relationship argument " + index); - } - } catch (ClassCastException e) { - var cls = entity.getClass().getName(); - throw new IllegalArgumentException( - "Expected argument " + index + " to be a relationship but found a " + cls + " instead"); - } - } - index += 1; - } - buildSegments(); - } - - public InternalPath(Entity... alternatingNodeAndRel) { - this(Arrays.asList(alternatingNodeAndRel)); - } - - public InternalPath(List segments, List nodes, List relationships) { - this.segments = segments; - this.nodes = nodes; - this.relationships = relationships; - } - - private List newList(int size) { - return size == 0 ? Collections.emptyList() : new ArrayList<>(size); - } - - @Override - public int length() { - return relationships.size(); - } - - @Override - public boolean contains(TestNode node) { - return nodes.contains(node); - } - - @Override - public boolean contains(TestRelationship relationship) { - return relationships.contains(relationship); - } - - @Override - public Iterable nodes() { - return nodes; - } - - @Override - public Iterable relationships() { - return relationships; - } - - @Override - public TestNode start() { - return nodes.get(0); - } - - @Override - public TestNode end() { - return nodes.get(nodes.size() - 1); - } - - @Override - public Iterator iterator() { - return segments.iterator(); - } - - @Override - public Value asValue() { - return new PathValue(this); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - var segments1 = (InternalPath) o; - - return segments.equals(segments1.segments); - } - - @Override - public int hashCode() { - return segments.hashCode(); - } - - @Override - public String toString() { - - return "path" + segments; - } - - private void buildSegments() { - for (var i = 0; i < relationships.size(); i++) { - segments.add(new SelfContainedSegment(nodes.get(i), relationships.get(i), nodes.get(i + 1))); - } - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalPoint2D.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalPoint2D.java deleted file mode 100644 index 9bc59f814a..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalPoint2D.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import org.neo4j.driver.internal.bolt.api.values.Point; - -public record InternalPoint2D(int srid, double x, double y) implements Point { - - @Override - public double z() { - return Double.NaN; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - var that = (InternalPoint2D) o; - return srid == that.srid && Double.compare(that.x, x) == 0 && Double.compare(that.y, y) == 0; - } - - @Override - public String toString() { - return "Point{" + "srid=" + srid + ", x=" + x + ", y=" + y + '}'; - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalPoint3D.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalPoint3D.java deleted file mode 100644 index 8759104339..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalPoint3D.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import org.neo4j.driver.internal.bolt.api.values.Point; - -public record InternalPoint3D(int srid, double x, double y, double z) implements Point { - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - var that = (InternalPoint3D) o; - return srid == that.srid - && Double.compare(that.x, x) == 0 - && Double.compare(that.y, y) == 0 - && Double.compare(that.z, z) == 0; - } - - @Override - public String toString() { - return "Point{" + "srid=" + srid + ", x=" + x + ", y=" + y + ", z=" + z + '}'; - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalRelationship.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalRelationship.java deleted file mode 100644 index 58752c7851..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/InternalRelationship.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import java.util.Collections; -import java.util.Map; -import org.neo4j.bolt.api.test.values.TestRelationship; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public class InternalRelationship extends InternalEntity implements TestRelationship { - private long start; - private String startElementId; - private long end; - private String endElementId; - private final String type; - - public InternalRelationship(long id, long start, long end, String type) { - this(id, start, end, type, Collections.emptyMap()); - } - - public InternalRelationship(long id, long start, long end, String type, Map properties) { - this(id, String.valueOf(id), start, String.valueOf(start), end, String.valueOf(end), type, properties); - } - - public InternalRelationship( - long id, - String elementId, - long start, - String startElementId, - long end, - String endElementId, - String type, - Map properties) { - super(id, elementId, properties); - this.start = start; - this.startElementId = startElementId; - this.end = end; - this.endElementId = endElementId; - this.type = type; - } - - /** - * Modify the start/end identities of this relationship - */ - public void setStartAndEnd(long start, String startElementId, long end, String endElementId) { - this.start = start; - this.startElementId = startElementId; - this.end = end; - this.endElementId = endElementId; - } - - @Override - @Deprecated - public long startNodeId() { - return start; - } - - @Override - public String startNodeElementId() { - return startElementId; - } - - @Override - @Deprecated - public long endNodeId() { - return end; - } - - @Override - public String endNodeElementId() { - return endElementId; - } - - @Override - public String typeString() { - return type; - } - - @Override - public Value asValue() { - return new RelationshipValue(this); - } - - @Override - @SuppressWarnings("deprecation") - public String toString() { - return String.format("relationship<%s>", id()); - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/ListValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/ListValue.java deleted file mode 100644 index 2c5f4d5e3a..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/ListValue.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import java.util.Arrays; -import java.util.Iterator; -import org.neo4j.driver.internal.bolt.api.values.Type; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public class ListValue extends ValueAdapter { - private final Value[] values; - - public ListValue(Value... values) { - if (values == null) { - throw new IllegalArgumentException("Cannot construct ListValue from null"); - } - this.values = values; - } - - @Override - public boolean isEmpty() { - return values.length == 0; - } - - @Override - public int size() { - return values.length; - } - - @Override - public Iterable values() { - return () -> new Iterator<>() { - private int cursor = 0; - - @Override - public boolean hasNext() { - return cursor < values.length; - } - - @Override - public Value next() { - return values[cursor++]; - } - - @Override - public void remove() {} - }; - } - - @Override - public Type type() { - return Type.LIST; - } - - @Override - public String toString() { - return Arrays.toString(values); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - var otherValues = (ListValue) o; - return Arrays.equals(values, otherValues.values); - } - - @Override - public int hashCode() { - return Arrays.hashCode(values); - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/LocalDateTimeValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/LocalDateTimeValue.java deleted file mode 100644 index 95b7e2926b..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/LocalDateTimeValue.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import java.time.LocalDateTime; -import org.neo4j.driver.internal.bolt.api.values.Type; - -public class LocalDateTimeValue extends ObjectValueAdapter { - public LocalDateTimeValue(LocalDateTime localDateTime) { - super(localDateTime); - } - - @Override - public LocalDateTime asLocalDateTime() { - return asObject(); - } - - @Override - public Type type() { - return Type.LOCAL_DATE_TIME; - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/LocalTimeValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/LocalTimeValue.java deleted file mode 100644 index 5e794299be..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/LocalTimeValue.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import java.time.LocalTime; -import org.neo4j.driver.internal.bolt.api.values.Type; - -public class LocalTimeValue extends ObjectValueAdapter { - public LocalTimeValue(LocalTime time) { - super(time); - } - - @Override - public LocalTime asLocalTime() { - return asObject(); - } - - @Override - public Type type() { - return Type.LOCAL_TIME; - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/LossyCoercion.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/LossyCoercion.java deleted file mode 100644 index 1c1e10c24f..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/LossyCoercion.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import static java.lang.String.format; - -import java.io.Serial; - -public class LossyCoercion extends ValueException { - @Serial - private static final long serialVersionUID = -6259981390929065201L; - - public LossyCoercion(String sourceTypeName, String destinationTypeName) { - super(format("Cannot coerce %s to %s without losing precision", sourceTypeName, destinationTypeName)); - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/MapAccessorWithDefaultValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/MapAccessorWithDefaultValue.java deleted file mode 100644 index a3b9ed134c..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/MapAccessorWithDefaultValue.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import org.neo4j.driver.internal.bolt.api.values.Value; - -public interface MapAccessorWithDefaultValue extends Value {} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/MapValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/MapValue.java deleted file mode 100644 index 02cf6bc600..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/MapValue.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import java.util.Map; -import java.util.function.Function; -import org.neo4j.driver.internal.bolt.api.values.Type; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public class MapValue extends ValueAdapter { - private final Map val; - - public MapValue(Map val) { - if (val == null) { - throw new IllegalArgumentException("Cannot construct MapValue from null"); - } - this.val = val; - } - - @Override - public boolean isEmpty() { - return val.isEmpty(); - } - - @Override - public Map asMap(Function mapFunction) { - return Extract.map(val, mapFunction); - } - - @Override - public int size() { - return val.size(); - } - - @Override - public boolean containsKey(String key) { - return val.containsKey(key); - } - - @Override - public Iterable keys() { - return val.keySet(); - } - - @Override - public Iterable values() { - return val.values(); - } - - @Override - public Value get(String key) { - var value = val.get(key); - return value == null ? NullValue.NULL : value; - } - - @Override - public String toString() { - return "MapValue{" + "val=" + val + '}'; - } - - @Override - public Type type() { - return Type.MAP; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - var values = (MapValue) o; - return val.equals(values.val); - } - - @Override - public int hashCode() { - return val.hashCode(); - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/NodeValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/NodeValue.java deleted file mode 100644 index 0f02996d0a..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/NodeValue.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import org.neo4j.bolt.api.test.values.TestNode; -import org.neo4j.driver.internal.bolt.api.values.Type; - -public class NodeValue extends EntityValueAdapter { - public NodeValue(TestNode adapted) { - super(adapted); - } - - @Override - public TestNode asNode() { - return asEntity(); - } - - @Override - public Type type() { - return Type.NODE; - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/NotMultiValued.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/NotMultiValued.java deleted file mode 100644 index 53a1cbd65b..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/NotMultiValued.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import java.io.Serial; - -public class NotMultiValued extends ValueException { - @Serial - private static final long serialVersionUID = -7380569883011364090L; - - public NotMultiValued(String message) { - super(message); - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/NullValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/NullValue.java deleted file mode 100644 index b6050c3c19..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/NullValue.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import org.neo4j.driver.internal.bolt.api.values.Type; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public final class NullValue extends ValueAdapter { - public static final Value NULL = new NullValue(); - - private NullValue() {} - - @Override - public boolean isNull() { - return true; - } - - @Override - public String asString() { - return "null"; - } - - @Override - public Type type() { - return Type.NULL; - } - - @SuppressWarnings("EqualsWhichDoesntCheckParameterClass") - @Override - public boolean equals(Object obj) { - return obj == NULL; - } - - @Override - public int hashCode() { - return 0; - } - - @Override - public String toString() { - return "NULL"; - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/NumberValueAdapter.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/NumberValueAdapter.java deleted file mode 100644 index 4c15502bcb..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/NumberValueAdapter.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -public abstract class NumberValueAdapter extends ValueAdapter { - public final V asObject() { - return asNumber(); - } - - public abstract V asNumber(); -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/ObjectValueAdapter.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/ObjectValueAdapter.java deleted file mode 100644 index 957041d229..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/ObjectValueAdapter.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import static java.lang.String.format; - -import java.util.Objects; - -public abstract class ObjectValueAdapter extends ValueAdapter { - private final V adapted; - - protected ObjectValueAdapter(V adapted) { - if (adapted == null) { - throw new IllegalArgumentException( - format("Cannot construct %s from null", getClass().getSimpleName())); - } - this.adapted = adapted; - } - - public final V asObject() { - return adapted; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - var that = (ObjectValueAdapter) o; - return Objects.equals(adapted, that.adapted); - } - - @Override - public int hashCode() { - return adapted.hashCode(); - } - - @Override - public String toString() { - return adapted.toString(); - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/PathValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/PathValue.java deleted file mode 100644 index 9e7fb83867..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/PathValue.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import org.neo4j.bolt.api.test.values.TestPath; -import org.neo4j.driver.internal.bolt.api.values.Type; - -public class PathValue extends ObjectValueAdapter { - public PathValue(TestPath adapted) { - super(adapted); - } - - @Override - public int size() { - return asObject().length(); - } - - @Override - public Type type() { - return Type.PATH; - } - - @Override - public TestPath asPath() { - return asObject(); - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/PointValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/PointValue.java deleted file mode 100644 index 54ef423534..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/PointValue.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import org.neo4j.driver.internal.bolt.api.values.Point; -import org.neo4j.driver.internal.bolt.api.values.Type; - -public class PointValue extends ObjectValueAdapter { - public PointValue(Point point) { - super(point); - } - - @Override - public Point asPoint() { - return asObject(); - } - - @Override - public Type type() { - return Type.POINT; - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/RelationshipValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/RelationshipValue.java deleted file mode 100644 index 0f50a2a27f..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/RelationshipValue.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import org.neo4j.bolt.api.test.values.TestRelationship; -import org.neo4j.driver.internal.bolt.api.values.Type; - -public class RelationshipValue extends EntityValueAdapter { - public RelationshipValue(TestRelationship adapted) { - super(adapted); - } - - @Override - public Type type() { - return Type.RELATIONSHIP; - } - - @Override - public TestRelationship asRelationship() { - return asEntity(); - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/StringValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/StringValue.java deleted file mode 100644 index bbd95e7cd0..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/StringValue.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import java.util.Objects; -import org.neo4j.driver.internal.bolt.api.values.Type; - -public class StringValue extends ValueAdapter { - private final String val; - - public StringValue(String val) { - if (val == null) { - throw new IllegalArgumentException("Cannot construct StringValue from null"); - } - this.val = val; - } - - @Override - public boolean isEmpty() { - return val.isEmpty(); - } - - @Override - public int size() { - return val.length(); - } - - @Override - public String asString() { - return val; - } - - @Override - public String toString() { - return String.format("\"%s\"", val.replace("\"", "\\\"")); - } - - @Override - public Type type() { - return Type.STRING; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - var that = (StringValue) o; - return Objects.equals(val, that.val); - } - - @Override - public int hashCode() { - return val.hashCode(); - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/TimeValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/TimeValue.java deleted file mode 100644 index 90db8e7a93..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/TimeValue.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import java.time.OffsetTime; -import org.neo4j.driver.internal.bolt.api.values.Type; - -public class TimeValue extends ObjectValueAdapter { - public TimeValue(OffsetTime time) { - super(time); - } - - @Override - public OffsetTime asOffsetTime() { - return asObject(); - } - - @Override - public Type type() { - return Type.TIME; - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/Uncoercible.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/Uncoercible.java deleted file mode 100644 index 3af6c5c8f9..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/Uncoercible.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import static java.lang.String.format; - -import java.io.Serial; - -public class Uncoercible extends ValueException { - @Serial - private static final long serialVersionUID = -6259981390929065201L; - - public Uncoercible(String sourceTypeName, String destinationTypeName) { - super(format("Cannot coerce %s to %s", sourceTypeName, destinationTypeName)); - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/Unsizable.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/Unsizable.java deleted file mode 100644 index 071d3cdea1..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/Unsizable.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import java.io.Serial; - -public class Unsizable extends ValueException { - @Serial - private static final long serialVersionUID = 741487155344252339L; - - public Unsizable(String message) { - super(message); - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/UnsupportedDateTimeValue.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/UnsupportedDateTimeValue.java deleted file mode 100644 index f7f30530db..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/UnsupportedDateTimeValue.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import java.lang.reflect.InvocationTargetException; -import java.time.DateTimeException; -import java.time.ZonedDateTime; -import org.neo4j.driver.internal.bolt.api.values.Type; - -public class UnsupportedDateTimeValue extends ValueAdapter { - final DateTimeException exception; - - public UnsupportedDateTimeValue(DateTimeException exception) { - this.exception = exception; - } - - @Override - public ZonedDateTime asZonedDateTime() { - throw instantiateDateTimeException(); - } - - @Override - public Type type() { - return Type.DATE_TIME; - } - - @Override - public boolean equals(Object obj) { - return this == obj; - } - - @Override - public int hashCode() { - return System.identityHashCode(this); - } - - @Override - public String toString() { - return "Unsupported datetime value."; - } - - private DateTimeException instantiateDateTimeException() { - DateTimeException newException; - try { - newException = exception - .getClass() - .getDeclaredConstructor(String.class, Throwable.class) - .newInstance(exception.getMessage(), exception); - } catch (NoSuchMethodException - | InvocationTargetException - | InstantiationException - | IllegalAccessException e) { - newException = new DateTimeException(exception.getMessage(), exception); - } - return newException; - } -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/ValueAdapter.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/ValueAdapter.java deleted file mode 100644 index bf712c298b..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/ValueAdapter.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import static java.util.Collections.emptyList; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZonedDateTime; -import java.util.Map; -import java.util.function.Function; -import org.neo4j.bolt.api.test.values.TestNode; -import org.neo4j.bolt.api.test.values.TestPath; -import org.neo4j.bolt.api.test.values.TestRelationship; -import org.neo4j.bolt.api.test.values.TestValue; -import org.neo4j.driver.internal.bolt.api.values.IsoDuration; -import org.neo4j.driver.internal.bolt.api.values.Point; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public abstract class ValueAdapter extends InternalMapAccessorWithDefaultValue implements TestValue { - @Override - public Value asValue() { - return this; - } - - @Override - public boolean isNull() { - return false; - } - - @Override - public boolean containsKey(String key) { - throw new NotMultiValued(type().name() + " is not a keyed collection"); - } - - @Override - public String asString() { - throw new Uncoercible(type().name(), "Java String"); - } - - @Override - public long asLong() { - throw new Uncoercible(type().name(), "Java long"); - } - - @Override - public double asDouble() { - throw new Uncoercible(type().name(), "Java double"); - } - - @Override - public boolean asBoolean() { - throw new Uncoercible(type().name(), "Java boolean"); - } - - @Override - public Map asMap(Function mapFunction) { - throw new Uncoercible(type().name(), "Java Map"); - } - - @Override - public LocalDate asLocalDate() { - throw new Uncoercible(type().name(), "LocalDate"); - } - - @Override - public OffsetTime asOffsetTime() { - throw new Uncoercible(type().name(), "OffsetTime"); - } - - @Override - public LocalTime asLocalTime() { - throw new Uncoercible(type().name(), "LocalTime"); - } - - @Override - public LocalDateTime asLocalDateTime() { - throw new Uncoercible(type().name(), "LocalDateTime"); - } - - @Override - public ZonedDateTime asZonedDateTime() { - throw new Uncoercible(type().name(), "ZonedDateTime"); - } - - @Override - public IsoDuration asIsoDuration() { - throw new Uncoercible(type().name(), "Duration"); - } - - @Override - public Point asPoint() { - throw new Uncoercible(type().name(), "Point"); - } - - @Override - public Value get(String key) { - throw new NotMultiValued(type().name() + " is not a keyed collection"); - } - - @Override - public int size() { - throw new Unsizable(type().name() + " does not have size"); - } - - @Override - public Iterable keys() { - return emptyList(); - } - - @Override - public boolean isEmpty() { - return !values().iterator().hasNext(); - } - - @Override - public Iterable values() { - throw new NotMultiValued(type().name() + " is not iterable"); - } - - @Override - public byte[] asByteArray() { - throw new Uncoercible(type().name(), "byte[]"); - } - - @Override - public TestNode asNode() { - throw new Uncoercible(type().name(), "Node"); - } - - @Override - public TestRelationship asRelationship() { - throw new Uncoercible(type().name(), "Relationship"); - } - - @Override - public TestPath asPath() { - throw new Uncoercible(type().name(), "Path"); - } - - // Force implementation - @Override - public abstract boolean equals(Object obj); - - // Force implementation - @Override - public abstract int hashCode(); - - // Force implementation - @Override - public abstract String toString(); -} diff --git a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/ValueException.java b/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/ValueException.java deleted file mode 100644 index 709754138f..0000000000 --- a/bolt-api-test-values/src/main/java/org/neo4j/bolt/api/test/values/impl/ValueException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.bolt.api.test.values.impl; - -import java.io.Serial; - -/** - * A ValueException indicates that the client has carried out an operation on values incorrectly. - * @since 1.0 - */ -public class ValueException extends RuntimeException { - @Serial - private static final long serialVersionUID = -1269336313727174998L; - - public ValueException(String message) { - super(message); - } -} diff --git a/bolt-api/LICENSES.txt b/bolt-api/LICENSES.txt deleted file mode 100644 index f8e0fd3292..0000000000 --- a/bolt-api/LICENSES.txt +++ /dev/null @@ -1,5 +0,0 @@ -This file contains the full license text of the included third party -libraries. For an overview of the licenses see the NOTICE.txt file. - - - diff --git a/bolt-api/NOTICE.txt b/bolt-api/NOTICE.txt deleted file mode 100644 index c3bf48c6fc..0000000000 --- a/bolt-api/NOTICE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) "Neo4j" -Neo4j Sweden AB [https://neo4j.com] - -This file is part of Neo4j. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -Full license texts are found in LICENSES.txt. - - -Third-party licenses --------------------- - diff --git a/bolt-api/pom.xml b/bolt-api/pom.xml deleted file mode 100644 index cf2218d953..0000000000 --- a/bolt-api/pom.xml +++ /dev/null @@ -1,73 +0,0 @@ - - 4.0.0 - - - org.neo4j.driver - neo4j-java-driver-parent - 5.28-SNAPSHOT - - - neo4j-bolt-api - - jar - Neo4j Bolt API - https://github.com/neo4j/neo4j-java-driver - - - ${project.basedir}/.. - ,-try - - - - - - org.mockito - mockito-core - - - org.junit.jupiter - junit-jupiter - - - org.bouncycastle - bcprov-jdk18on - - - org.bouncycastle - bcpkix-jdk18on - - - - - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-javadoc-plugin - - - org.apache.maven.plugins - maven-failsafe-plugin - - - org.apache.maven.surefire - surefire-junit-platform - ${surefire.and.failsafe.version} - - - - - - - - scm:git:git://github.com/neo4j/neo4j-java-driver.git - scm:git:git@github.com:neo4j/neo4j-java-driver.git - https://github.com/neo4j/neo4j-java-driver - - - diff --git a/bolt-api/src/main/java/module-info.java b/bolt-api/src/main/java/module-info.java deleted file mode 100644 index fd904f3e9c..0000000000 --- a/bolt-api/src/main/java/module-info.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * The Neo4j Bolt API module. - */ -module org.neo4j.bolt.api { - exports org.neo4j.driver.internal.bolt.api; - exports org.neo4j.driver.internal.bolt.api.exception; - exports org.neo4j.driver.internal.bolt.api.summary; - exports org.neo4j.driver.internal.bolt.api.values; - exports org.neo4j.driver.internal.bolt.api.ssl; -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/AccessMode.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/AccessMode.java deleted file mode 100644 index e4a6eb51ae..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/AccessMode.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -public enum AccessMode { - READ, - WRITE -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/AuthInfo.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/AuthInfo.java deleted file mode 100644 index d47380b58a..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/AuthInfo.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -public interface AuthInfo { - AuthToken authToken(); - - long authAckMillis(); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/AuthToken.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/AuthToken.java deleted file mode 100644 index 349965e152..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/AuthToken.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public sealed interface AuthToken permits AuthTokenImpl { - Map asMap(); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/AuthTokenImpl.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/AuthTokenImpl.java deleted file mode 100644 index a4e309caca..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/AuthTokenImpl.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.Value; - -record AuthTokenImpl(Map map) implements AuthToken { - @Override - public Map asMap() { - return map; - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/AuthTokens.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/AuthTokens.java deleted file mode 100644 index 2d68ed2c90..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/AuthTokens.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; - -public final class AuthTokens { - private static final String SCHEME_KEY = "scheme"; - private static final String PRINCIPAL_KEY = "principal"; - private static final String CREDENTIALS_KEY = "credentials"; - private static final String REALM_KEY = "realm"; - private static final String PARAMETERS_KEY = "parameters"; - - private AuthTokens() {} - - public static AuthToken basic(String username, String password, String realm, ValueFactory valueFactory) { - Objects.requireNonNull(username); - Objects.requireNonNull(password); - Objects.requireNonNull(valueFactory); - - var map = new HashMap(4); - map.put(SCHEME_KEY, valueFactory.value("basic")); - map.put(PRINCIPAL_KEY, valueFactory.value(username)); - map.put(CREDENTIALS_KEY, valueFactory.value(password)); - if (realm != null) { - map.put(REALM_KEY, valueFactory.value(realm)); - } - return new AuthTokenImpl(Collections.unmodifiableMap(map)); - } - - public static AuthToken bearer(String token, ValueFactory valueFactory) { - Objects.requireNonNull(token); - Objects.requireNonNull(valueFactory); - - var map = new HashMap(2); - map.put(SCHEME_KEY, valueFactory.value("bearer")); - map.put(CREDENTIALS_KEY, valueFactory.value(token)); - return new AuthTokenImpl(Collections.unmodifiableMap(map)); - } - - public static AuthToken kerberos(String base64EncodedTicket, ValueFactory valueFactory) { - Objects.requireNonNull(base64EncodedTicket); - Objects.requireNonNull(valueFactory); - - var map = new HashMap(3); - map.put(SCHEME_KEY, valueFactory.value("kerberos")); - map.put(PRINCIPAL_KEY, valueFactory.value("")); // This empty string is required for backwards compatibility. - map.put(CREDENTIALS_KEY, valueFactory.value(base64EncodedTicket)); - return new AuthTokenImpl(Collections.unmodifiableMap(map)); - } - - public static AuthToken none(ValueFactory valueFactory) { - Objects.requireNonNull(valueFactory); - - return new AuthTokenImpl(Collections.singletonMap(SCHEME_KEY, valueFactory.value("none"))); - } - - public static AuthToken custom(Map map) { - Objects.requireNonNull(map); - - return new AuthTokenImpl(Collections.unmodifiableMap(map)); - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/BasicResponseHandler.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/BasicResponseHandler.java deleted file mode 100644 index b4f71e1692..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/BasicResponseHandler.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.CompletionStage; -import org.neo4j.driver.internal.bolt.api.exception.BoltException; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.CommitSummary; -import org.neo4j.driver.internal.bolt.api.summary.DiscardSummary; -import org.neo4j.driver.internal.bolt.api.summary.LogoffSummary; -import org.neo4j.driver.internal.bolt.api.summary.LogonSummary; -import org.neo4j.driver.internal.bolt.api.summary.PullSummary; -import org.neo4j.driver.internal.bolt.api.summary.ResetSummary; -import org.neo4j.driver.internal.bolt.api.summary.RollbackSummary; -import org.neo4j.driver.internal.bolt.api.summary.RouteSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.summary.TelemetrySummary; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public final class BasicResponseHandler implements ResponseHandler { - private final CompletableFuture summariesFuture = new CompletableFuture<>(); - private final List valuesList = new ArrayList<>(); - - private BeginSummary beginSummary; - private RunSummary runSummary; - private PullSummary pullSummary; - private DiscardSummary discardSummary; - private CommitSummary commitSummary; - private RollbackSummary rollbackSummary; - private ResetSummary resetSummary; - private RouteSummary routeSummary; - private LogoffSummary logoffSummary; - private LogonSummary logonSummary; - private TelemetrySummary telemetrySummary; - private int ignored; - private Throwable error; - - public BasicResponseHandler() {} - - public CompletionStage summaries() { - return summariesFuture; - } - - @Override - public void onError(Throwable throwable) { - if (throwable instanceof CompletionException) { - throwable = throwable.getCause(); - } - if (error == null) { - error = throwable; - } else { - if (error instanceof BoltException && !(throwable instanceof BoltException)) { - // higher order error has occurred - error = throwable; - } - } - } - - @Override - public void onBeginSummary(BeginSummary summary) { - beginSummary = summary; - } - - @Override - public void onRunSummary(RunSummary summary) { - runSummary = summary; - } - - @Override - public void onRecord(Value[] fields) { - valuesList.add(fields); - } - - @Override - public void onPullSummary(PullSummary summary) { - pullSummary = summary; - } - - @Override - public void onDiscardSummary(DiscardSummary summary) { - discardSummary = summary; - } - - @Override - public void onCommitSummary(CommitSummary summary) { - commitSummary = summary; - } - - @Override - public void onRollbackSummary(RollbackSummary summary) { - rollbackSummary = summary; - } - - @Override - public void onResetSummary(ResetSummary summary) { - resetSummary = summary; - } - - @Override - public void onRouteSummary(RouteSummary summary) { - routeSummary = summary; - } - - @Override - public void onLogoffSummary(LogoffSummary summary) { - logoffSummary = summary; - } - - @Override - public void onLogonSummary(LogonSummary summary) { - logonSummary = summary; - } - - @Override - public void onTelemetrySummary(TelemetrySummary summary) { - telemetrySummary = summary; - } - - @Override - public void onIgnored() { - ignored++; - } - - @Override - public void onComplete() { - if (error != null) { - summariesFuture.completeExceptionally(error); - } else { - summariesFuture.complete(new Summaries( - beginSummary, - runSummary, - valuesList, - pullSummary, - discardSummary, - commitSummary, - rollbackSummary, - resetSummary, - routeSummary, - logoffSummary, - logonSummary, - telemetrySummary, - ignored)); - } - } - - public record Summaries( - BeginSummary beginSummary, - RunSummary runSummary, - List valuesList, - PullSummary pullSummary, - DiscardSummary discardSummary, - CommitSummary commitSummary, - RollbackSummary rollbackSummary, - ResetSummary resetSummary, - RouteSummary routeSummary, - LogoffSummary logoffSummary, - LogonSummary logonSummary, - TelemetrySummary telemetrySummary, - int ignored) {} -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/BoltAgent.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/BoltAgent.java deleted file mode 100644 index 50b4b7c85a..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/BoltAgent.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -public record BoltAgent(String product, String platform, String language, String languageDetails) {} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/BoltConnection.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/BoltConnection.java deleted file mode 100644 index 474a1ab393..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/BoltConnection.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import java.time.Duration; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.CompletionStage; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public interface BoltConnection { - CompletionStage onLoop(); - - CompletionStage route(DatabaseName databaseName, String impersonatedUser, Set bookmarks); - - CompletionStage beginTransaction( - DatabaseName databaseName, - AccessMode accessMode, - String impersonatedUser, - Set bookmarks, - TransactionType transactionType, - Duration txTimeout, - Map txMetadata, - String txType, - NotificationConfig notificationConfig); - - CompletionStage runInAutoCommitTransaction( - DatabaseName databaseName, - AccessMode accessMode, - String impersonatedUser, - Set bookmarks, - String query, - Map parameters, - Duration txTimeout, - Map txMetadata, - NotificationConfig notificationConfig); - - CompletionStage run(String query, Map parameters); - - CompletionStage pull(long qid, long request); - - CompletionStage discard(long qid, long number); - - CompletionStage commit(); - - CompletionStage rollback(); - - CompletionStage reset(); - - CompletionStage logoff(); - - CompletionStage logon(AuthToken authToken); - - CompletionStage telemetry(TelemetryApi telemetryApi); - - CompletionStage clear(); - - CompletionStage flush(ResponseHandler handler); - - CompletionStage forceClose(String reason); - - CompletionStage close(); - - // ----- STATE UPDATES ----- - - CompletionStage setReadTimeout(Duration duration); - - // ----- MUTABLE DATA ----- - - BoltConnectionState state(); - - CompletionStage authInfo(); - - // ----- IMMUTABLE DATA ----- - - String serverAgent(); - - BoltServerAddress serverAddress(); - - BoltProtocolVersion protocolVersion(); - - boolean telemetrySupported(); - - boolean serverSideRoutingEnabled(); - - Optional defaultReadTimeout(); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/BoltConnectionProvider.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/BoltConnectionProvider.java deleted file mode 100644 index 54883b8a2d..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/BoltConnectionProvider.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletionStage; -import java.util.function.Consumer; -import java.util.function.Supplier; - -public interface BoltConnectionProvider { - CompletionStage connect( - BoltServerAddress address, - RoutingContext routingContext, - BoltAgent boltAgent, - String userAgent, - int connectTimeoutMillis, - SecurityPlan securityPlan, - DatabaseName databaseName, - Supplier> authTokenStageSupplier, - AccessMode mode, - Set bookmarks, - String impersonatedUser, - BoltProtocolVersion minVersion, - NotificationConfig notificationConfig, - Consumer databaseNameConsumer, - Map additionalParameters); - - CompletionStage verifyConnectivity( - BoltServerAddress address, - RoutingContext routingContext, - BoltAgent boltAgent, - String userAgent, - int connectTimeoutMillis, - SecurityPlan securityPlan, - AuthToken authToken); - - CompletionStage supportsMultiDb( - BoltServerAddress address, - RoutingContext routingContext, - BoltAgent boltAgent, - String userAgent, - int connectTimeoutMillis, - SecurityPlan securityPlan, - AuthToken authToken); - - CompletionStage supportsSessionAuth( - BoltServerAddress address, - RoutingContext routingContext, - BoltAgent boltAgent, - String userAgent, - int connectTimeoutMillis, - SecurityPlan securityPlan, - AuthToken authToken); - - CompletionStage close(); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/BoltConnectionState.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/BoltConnectionState.java deleted file mode 100644 index f979af9af7..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/BoltConnectionState.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -public enum BoltConnectionState { - OPEN, - ERROR, - FAILURE, - CLOSED -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/BoltProtocolVersion.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/BoltProtocolVersion.java deleted file mode 100644 index 31c9655f51..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/BoltProtocolVersion.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import java.util.Objects; - -public class BoltProtocolVersion implements Comparable { - private final int majorVersion; - private final int minorVersion; - - public BoltProtocolVersion(int majorVersion, int minorVersion) { - this.majorVersion = majorVersion; - this.minorVersion = minorVersion; - } - - public static BoltProtocolVersion fromRawBytes(int rawVersion) { - var major = rawVersion & 0x000000FF; - var minor = (rawVersion >> 8) & 0x000000FF; - - return new BoltProtocolVersion(major, minor); - } - - public long getMinorVersion() { - return minorVersion; - } - - public long getMajorVersion() { - return majorVersion; - } - - public int toInt() { - var shiftedMinor = minorVersion << 8; - return shiftedMinor | majorVersion; - } - - public int toIntRange(BoltProtocolVersion minVersion) { - if (majorVersion != minVersion.majorVersion) { - throw new IllegalArgumentException("Versions should be from the same major version"); - } else if (minorVersion < minVersion.minorVersion) { - throw new IllegalArgumentException("Max version should be newer than min version"); - } - var range = minorVersion - minVersion.minorVersion; - var shiftedRange = range << 16; - return shiftedRange | toInt(); - } - - /** - * @return the version in format X.Y where X is the major version and Y is the minor version - */ - @Override - public String toString() { - return String.format("%d.%d", majorVersion, minorVersion); - } - - @Override - public int hashCode() { - return Objects.hash(minorVersion, majorVersion); - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } else if (!(o instanceof BoltProtocolVersion other)) { - return false; - } else { - return this.getMajorVersion() == other.getMajorVersion() - && this.getMinorVersion() == other.getMinorVersion(); - } - } - - @Override - public int compareTo(BoltProtocolVersion other) { - var result = Integer.compare(majorVersion, other.majorVersion); - - if (result == 0) { - return Integer.compare(minorVersion, other.minorVersion); - } - - return result; - } - - public static boolean isHttp(BoltProtocolVersion protocolVersion) { - // server would respond with `HTTP..` We read 4 bytes to figure out the version. The first two are not used - // and therefore parse the `P` (80) for major and `T` (84) for minor. - return protocolVersion.getMajorVersion() == 80 && protocolVersion.getMinorVersion() == 84; - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/BoltServerAddress.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/BoltServerAddress.java deleted file mode 100644 index c345307e90..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/BoltServerAddress.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import static java.util.Objects.requireNonNull; - -import java.net.URI; -import java.util.Objects; -import java.util.stream.Stream; - -/** - * Holds a host and port pair that denotes a Bolt server address. - */ -public class BoltServerAddress { - public static final int DEFAULT_PORT = 7687; - public static final BoltServerAddress LOCAL_DEFAULT = new BoltServerAddress("localhost", DEFAULT_PORT); - - protected final String host; // Host or IP address. - private final String - connectionHost; // Either is equal to the host or is explicitly provided on creation and is expected to be a - // resolved IP address. - protected final int port; - private final String stringValue; - - public BoltServerAddress(String address) { - this(uriFrom(address)); - } - - public BoltServerAddress(URI uri) { - this(hostFrom(uri), portFrom(uri)); - } - - public BoltServerAddress(String host, int port) { - this(host, host, port); - } - - public BoltServerAddress(String host, String connectionHost, int port) { - this.host = requireNonNull(host, "host"); - this.connectionHost = requireNonNull(connectionHost, "connectionHost"); - this.port = requireValidPort(port); - this.stringValue = host.equals(connectionHost) - ? String.format("%s:%d", host, port) - : String.format("%s(%s):%d", host, connectionHost, port); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - var address = (BoltServerAddress) o; - return port == address.port && host.equals(address.host) && connectionHost.equals(address.connectionHost); - } - - @Override - public int hashCode() { - return Objects.hash(host, connectionHost, port); - } - - @Override - public String toString() { - return stringValue; - } - - public String host() { - return host; - } - - public int port() { - return port; - } - - public String connectionHost() { - return connectionHost; - } - - /** - * Create a stream of unicast addresses. - *

- * While this implementation just returns a stream of itself, the subclasses may provide multiple addresses. - * - * @return stream of unicast addresses. - */ - public Stream unicastStream() { - return Stream.of(this); - } - - private static String hostFrom(URI uri) { - var host = uri.getHost(); - if (host == null) { - throw invalidAddressFormat(uri); - } - return host; - } - - private static int portFrom(URI uri) { - var port = uri.getPort(); - return port == -1 ? DEFAULT_PORT : port; - } - - @SuppressWarnings("DuplicatedCode") - private static URI uriFrom(String address) { - String scheme; - String hostPort; - - var schemeSplit = address.split("://"); - if (schemeSplit.length == 1) { - // URI can't parse addresses without scheme, prepend fake "bolt://" to reuse the parsing facility - scheme = "bolt://"; - hostPort = hostPortFrom(schemeSplit[0]); - } else if (schemeSplit.length == 2) { - scheme = schemeSplit[0] + "://"; - hostPort = hostPortFrom(schemeSplit[1]); - } else { - throw invalidAddressFormat(address); - } - - return URI.create(scheme + hostPort); - } - - private static String hostPortFrom(String address) { - if (address.startsWith("[")) { - // expected to be an IPv6 address like [::1] or [::1]:7687 - return address; - } - - var containsSingleColon = address.indexOf(":") == address.lastIndexOf(":"); - if (containsSingleColon) { - // expected to be an IPv4 address with or without port like 127.0.0.1 or 127.0.0.1:7687 - return address; - } - - // address contains multiple colons and does not start with '[' - // expected to be an IPv6 address without brackets - return "[" + address + "]"; - } - - private static RuntimeException invalidAddressFormat(URI uri) { - return invalidAddressFormat(uri.toString()); - } - - private static RuntimeException invalidAddressFormat(String address) { - return new IllegalArgumentException("Invalid address format `" + address + "`"); - } - - private static int requireValidPort(int port) { - if (port >= 0 && port <= 65_535) { - return port; - } - throw new IllegalArgumentException("Illegal port: " + port); - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ClusterComposition.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ClusterComposition.java deleted file mode 100644 index 81a59f0973..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ClusterComposition.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import java.util.LinkedHashSet; -import java.util.Objects; -import java.util.Set; - -public final class ClusterComposition { - private final Set readers; - private final Set writers; - private final Set routers; - private final long expirationTimestamp; - private final String databaseName; - - private ClusterComposition(long expirationTimestamp, String databaseName) { - this.readers = new LinkedHashSet<>(); - this.writers = new LinkedHashSet<>(); - this.routers = new LinkedHashSet<>(); - this.expirationTimestamp = expirationTimestamp; - this.databaseName = databaseName; - } - - public ClusterComposition( - long expirationTimestamp, - Set readers, - Set writers, - Set routers, - String databaseName) { - this(expirationTimestamp, databaseName); - this.readers.addAll(readers); - this.writers.addAll(writers); - this.routers.addAll(routers); - } - - public boolean hasWriters() { - return !writers.isEmpty(); - } - - public boolean hasRoutersAndReaders() { - return !routers.isEmpty() && !readers.isEmpty(); - } - - public Set readers() { - return new LinkedHashSet<>(readers); - } - - public Set writers() { - return new LinkedHashSet<>(writers); - } - - public Set routers() { - return new LinkedHashSet<>(routers); - } - - public long expirationTimestamp() { - return this.expirationTimestamp; - } - - public String databaseName() { - return databaseName; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - var that = (ClusterComposition) o; - return expirationTimestamp == that.expirationTimestamp - && Objects.equals(databaseName, that.databaseName) - && Objects.equals(readers, that.readers) - && Objects.equals(writers, that.writers) - && Objects.equals(routers, that.routers); - } - - @Override - public int hashCode() { - return Objects.hash(readers, writers, routers, expirationTimestamp, databaseName); - } - - @Override - public String toString() { - return "ClusterComposition{" + "readers=" - + readers + ", writers=" - + writers + ", routers=" - + routers + ", expirationTimestamp=" - + expirationTimestamp + ", databaseName=" - + databaseName + '}'; - } - - private Set servers(String role) { - return switch (role) { - case "READ" -> readers; - case "WRITE" -> writers; - case "ROUTE" -> routers; - default -> throw new IllegalArgumentException("invalid server role: " + role); - }; - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/DatabaseName.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/DatabaseName.java deleted file mode 100644 index c41b8ce160..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/DatabaseName.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import java.util.Optional; - -public interface DatabaseName { - Optional databaseName(); - - String description(); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/DatabaseNameUtil.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/DatabaseNameUtil.java deleted file mode 100644 index a0cef59063..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/DatabaseNameUtil.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import java.util.Objects; -import java.util.Optional; - -public final class DatabaseNameUtil { - static final String DEFAULT_DATABASE_NAME = null; - public static final String SYSTEM_DATABASE_NAME = "system"; - - private DatabaseNameUtil() {} - - private static final DatabaseName DEFAULT_DATABASE = new DatabaseName() { - @Override - public Optional databaseName() { - return Optional.empty(); - } - - @Override - public String description() { - return ""; - } - }; - private static final DatabaseName SYSTEM_DATABASE = new InternalDatabaseName(SYSTEM_DATABASE_NAME); - - public static DatabaseName defaultDatabase() { - return DEFAULT_DATABASE; - } - - public static DatabaseName systemDatabase() { - return SYSTEM_DATABASE; - } - - public static DatabaseName database(String name) { - if (Objects.equals(name, DEFAULT_DATABASE_NAME)) { - return defaultDatabase(); - } else if (Objects.equals(name, SYSTEM_DATABASE_NAME)) { - return systemDatabase(); - } - return new InternalDatabaseName(name); - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/DefaultDomainNameResolver.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/DefaultDomainNameResolver.java deleted file mode 100644 index 7e3cd4b585..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/DefaultDomainNameResolver.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import java.net.InetAddress; -import java.net.UnknownHostException; - -public class DefaultDomainNameResolver implements DomainNameResolver { - private static final DefaultDomainNameResolver INSTANCE = new DefaultDomainNameResolver(); - - public static DefaultDomainNameResolver getInstance() { - return INSTANCE; - } - - private DefaultDomainNameResolver() {} - - @Override - public InetAddress[] resolve(String name) throws UnknownHostException { - return InetAddress.getAllByName(name); - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/DomainNameResolver.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/DomainNameResolver.java deleted file mode 100644 index 5d8804a14b..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/DomainNameResolver.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import java.net.InetAddress; -import java.net.UnknownHostException; - -/** - * A resolver function used by the driver to resolve domain names. - */ -@FunctionalInterface -public interface DomainNameResolver { - /** - * Resolve the given domain name to a set of addresses. - * - * @param name the name to resolve. - * @return the resolved addresses. - * @throws UnknownHostException must be thrown if the given name can not be resolved to at least one address. - */ - InetAddress[] resolve(String name) throws UnknownHostException; -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/GqlError.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/GqlError.java deleted file mode 100644 index 08f2c79151..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/GqlError.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public record GqlError( - String gqlStatus, - String statusDescription, - String code, - String message, - Map diagnosticRecord, - GqlError cause) {} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/GqlStatusError.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/GqlStatusError.java deleted file mode 100644 index a3129e7770..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/GqlStatusError.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -public enum GqlStatusError { - UNKNOWN("50N42", "general processing exception - unexpected error"); - - private final String status; - private final String explanation; - - @SuppressWarnings("SameParameterValue") - GqlStatusError(String status, String explanation) { - this.status = status; - this.explanation = explanation; - } - - public String getStatus() { - return status; - } - - public String getStatusDescription(String message) { - return String.format("error: %s. %s", explanation, message); - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/InternalDatabaseName.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/InternalDatabaseName.java deleted file mode 100644 index f1bc317a8b..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/InternalDatabaseName.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import static java.util.Objects.requireNonNull; - -import java.util.Objects; -import java.util.Optional; - -public class InternalDatabaseName implements DatabaseName { - private final String databaseName; - - InternalDatabaseName(String databaseName) { - this.databaseName = requireNonNull(databaseName); - } - - @Override - public Optional databaseName() { - return Optional.of(databaseName); - } - - @Override - public String description() { - return databaseName; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - var that = (InternalDatabaseName) o; - return databaseName.equals(that.databaseName); - } - - @Override - public int hashCode() { - return Objects.hash(databaseName); - } - - @Override - public String toString() { - return "InternalDatabaseName{" + "databaseName='" + databaseName + '\'' + '}'; - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ListenerEvent.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ListenerEvent.java deleted file mode 100644 index c4745bae04..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ListenerEvent.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -public interface ListenerEvent { - void start(); - - T getSample(); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/LoggingProvider.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/LoggingProvider.java deleted file mode 100644 index d6c68dfeae..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/LoggingProvider.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -public interface LoggingProvider { - System.Logger getLog(Class cls); - - System.Logger getLog(String name); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/MetricsListener.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/MetricsListener.java deleted file mode 100644 index 597abc44ce..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/MetricsListener.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import java.util.function.IntSupplier; - -public interface MetricsListener { - /** - * Before creating a netty channel. - * - * @param poolId the id of the pool where the netty channel lives. - * @param creatingEvent a connection listener event registered when a connection is creating. - */ - void beforeCreating(String poolId, ListenerEvent creatingEvent); - - /** - * After a netty channel is created successfully. - * - * @param poolId the id of the pool where the netty channel lives. - */ - void afterCreated(String poolId, ListenerEvent creatingEvent); - - /** - * After a netty channel is created with a failure. - * @param poolId the id of the pool where the netty channel lives. - */ - void afterFailedToCreate(String poolId); - - /** - * After a netty channel is closed successfully. - * @param poolId the id of the pool where the netty channel lives. - */ - void afterClosed(String poolId); - - /** - * Before acquiring or creating a new netty channel from pool. - * - * @param poolId the id of the pool where the netty channel lives. - * @param acquireEvent a pool listener event registered in pool for this acquire event. - */ - void beforeAcquiringOrCreating(String poolId, ListenerEvent acquireEvent); - - /** - * After acquiring or creating a new netty channel from pool regardless it is successful or not. - * @param poolId the id of the pool where the netty channel lives. - */ - void afterAcquiringOrCreating(String poolId); - - /** - * After acquiring or creating a new netty channel from pool successfully. - * - * @param poolId the id of the pool where the netty channel lives. - * @param acquireEvent a pool listener event registered in pool for this acquire event. - */ - void afterAcquiredOrCreated(String poolId, ListenerEvent acquireEvent); - - /** - * After we failed to acquire a connection from pool within maximum connection acquisition timeout set by timeout. - * @param poolId the id of the pool where the netty channel lives. - */ - void afterTimedOutToAcquireOrCreate(String poolId); - - /** - * After acquiring or creating a new netty channel from pool successfully. - * - * @param poolId the id of the pool where the netty channel lives. - * @param inUseEvent a connection listener event fired from the newly created connection. - */ - void afterConnectionCreated(String poolId, ListenerEvent inUseEvent); - - /** - * After releasing a netty channel back to pool successfully. - * - * @param poolId the id of the pool where the netty channel lives. - * @param inUseEvent a connection listener event fired from the connection being released. - */ - void afterConnectionReleased(String poolId, ListenerEvent inUseEvent); - - ListenerEvent createListenerEvent(); - - void registerPoolMetrics( - String poolId, BoltServerAddress serverAddress, IntSupplier inUseSupplier, IntSupplier idleSupplier); - - void removePoolMetrics(String poolId); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/NotificationClassification.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/NotificationClassification.java deleted file mode 100644 index b9e72296f7..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/NotificationClassification.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import java.util.Arrays; -import java.util.Objects; -import java.util.Optional; - -public record NotificationClassification(Type type) { - public NotificationClassification { - Objects.requireNonNull(type, "type must not be null"); - } - - public enum Type { - HINT, - UNRECOGNIZED, - UNSUPPORTED, - PERFORMANCE, - DEPRECATION, - SECURITY, - TOPOLOGY, - GENERIC, - SCHEMA - } - - public static Optional valueOf(String value) { - return Arrays.stream(Type.values()) - .filter(type -> type.toString().equals(value)) - .findFirst() - .map(NotificationClassification::new); - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/NotificationConfig.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/NotificationConfig.java deleted file mode 100644 index 61124e2323..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/NotificationConfig.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import java.util.Set; - -public record NotificationConfig( - NotificationSeverity minimumSeverity, Set disabledClassifications) { - public static NotificationConfig defaultConfig() { - return new NotificationConfig(null, null); - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/NotificationSeverity.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/NotificationSeverity.java deleted file mode 100644 index 1b551b750b..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/NotificationSeverity.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import java.util.Arrays; -import java.util.Objects; -import java.util.Optional; - -public record NotificationSeverity(Type type, int level) implements Comparable { - public static final NotificationSeverity OFF = - new NotificationSeverity(NotificationSeverity.Type.OFF, Integer.MAX_VALUE); - - public static final NotificationSeverity INFORMATION = - new NotificationSeverity(NotificationSeverity.Type.INFORMATION, 800); - - public static final NotificationSeverity WARNING = new NotificationSeverity(NotificationSeverity.Type.WARNING, 900); - - public NotificationSeverity { - Objects.requireNonNull(type, "type must not be null"); - } - - @Override - public int compareTo(NotificationSeverity severity) { - return Integer.compare(this.level, severity.level()); - } - - public enum Type { - INFORMATION, - WARNING, - OFF - } - - @SuppressWarnings("DuplicatedCode") - public static Optional valueOf(String value) { - return Arrays.stream(Type.values()) - .filter(type -> type.toString().equals(value)) - .findFirst() - .map(type -> switch (type) { - case INFORMATION -> NotificationSeverity.INFORMATION; - case WARNING -> NotificationSeverity.WARNING; - case OFF -> NotificationSeverity.OFF; - }); - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ResponseHandler.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ResponseHandler.java deleted file mode 100644 index 9d78e66bbe..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ResponseHandler.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.CommitSummary; -import org.neo4j.driver.internal.bolt.api.summary.DiscardSummary; -import org.neo4j.driver.internal.bolt.api.summary.LogoffSummary; -import org.neo4j.driver.internal.bolt.api.summary.LogonSummary; -import org.neo4j.driver.internal.bolt.api.summary.PullSummary; -import org.neo4j.driver.internal.bolt.api.summary.ResetSummary; -import org.neo4j.driver.internal.bolt.api.summary.RollbackSummary; -import org.neo4j.driver.internal.bolt.api.summary.RouteSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.summary.TelemetrySummary; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public interface ResponseHandler { - - void onError(Throwable throwable); - - default void onBeginSummary(BeginSummary summary) { - // ignored - } - - default void onRunSummary(RunSummary summary) { - // ignored - } - - default void onRecord(Value[] fields) { - // ignored - } - - default void onPullSummary(PullSummary summary) { - // ignored - } - - default void onDiscardSummary(DiscardSummary summary) { - // ignored - } - - default void onCommitSummary(CommitSummary summary) { - // ignored - } - - default void onRollbackSummary(RollbackSummary summary) { - // ignored - } - - default void onResetSummary(ResetSummary summary) { - // ignored - } - - default void onRouteSummary(RouteSummary summary) { - // ignored - } - - default void onLogoffSummary(LogoffSummary summary) { - // ignored - } - - default void onLogonSummary(LogonSummary summary) { - // ignored - } - - default void onTelemetrySummary(TelemetrySummary summary) { - // ignored - } - - default void onIgnored() { - // ignored - } - - default void onComplete() { - // ignored - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ResultSummary.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ResultSummary.java deleted file mode 100644 index dfa191befa..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ResultSummary.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -/** - * The result summary of running a query. The result summary interface can be used to - * investigate details about the result, like the type of query run, how many and which - * kinds of updates have been executed, and query plan and profiling information if - * available. - *

- * The result summary is only available after all result records have been consumed. - *

- * Keeping the result summary around does not influence the lifecycle of any associated - * session and/or transaction. - * - * @author Neo4j Drivers Team - * @since 1.0.0 - */ -public interface ResultSummary { - - /** - * Returns counters for operations the query triggered. - * @return counters for operations the query triggered - */ - SummaryCounters counters(); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/RoutingContext.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/RoutingContext.java deleted file mode 100644 index 9a071d5f0b..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/RoutingContext.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import static java.util.Collections.emptyMap; -import static java.util.Collections.unmodifiableMap; -import static org.neo4j.driver.internal.bolt.api.Scheme.isRoutingScheme; - -import java.net.URI; -import java.util.HashMap; -import java.util.Map; - -public class RoutingContext { - - public static final RoutingContext EMPTY = new RoutingContext(); - private static final String ROUTING_ADDRESS_KEY = "address"; - - private final Map context; - private final boolean isServerRoutingEnabled; - - private RoutingContext() { - this.isServerRoutingEnabled = true; - this.context = emptyMap(); - } - - public RoutingContext(URI uri) { - this.isServerRoutingEnabled = isRoutingScheme(uri.getScheme()); - this.context = unmodifiableMap(parseParameters(uri)); - } - - public boolean isDefined() { - return context.size() > 1; - } - - public Map toMap() { - return context; - } - - public boolean isServerRoutingEnabled() { - return isServerRoutingEnabled; - } - - @Override - public String toString() { - return "RoutingContext" + context + " isServerRoutingEnabled=" + isServerRoutingEnabled; - } - - private static Map parseParameters(URI uri) { - var query = uri.getQuery(); - String address; - - if (uri.getPort() == -1) { - address = String.format("%s:%s", uri.getHost(), BoltServerAddress.DEFAULT_PORT); - } else { - address = String.format("%s:%s", uri.getHost(), uri.getPort()); - } - - Map parameters = new HashMap<>(); - parameters.put(ROUTING_ADDRESS_KEY, address); - - if (query == null || query.isEmpty()) { - return parameters; - } - - var pairs = query.split("&"); - for (var pair : pairs) { - var keyValue = pair.split("="); - if (keyValue.length != 2) { - throw new IllegalArgumentException("Invalid parameters: '" + pair + "' in URI '" + uri + "'"); - } - - var previousValue = - parameters.put(trimAndVerifyKey(keyValue[0], uri), trimAndVerify(keyValue[1], "value", uri)); - if (previousValue != null) { - throw new IllegalArgumentException( - "Duplicated query parameters with key '" + previousValue + "' in URI '" + uri + "'"); - } - } - return parameters; - } - - private static String trimAndVerifyKey(String s, URI uri) { - var trimmed = trimAndVerify(s, "key", uri); - - if (trimmed.equals(ROUTING_ADDRESS_KEY)) { - throw new IllegalArgumentException("The key 'address' is reserved for routing context."); - } - - return trimmed; - } - - private static String trimAndVerify(String string, String name, URI uri) { - var result = string.trim(); - if (result.isEmpty()) { - throw new IllegalArgumentException("Illegal empty " + name + " in URI query '" + uri + "'"); - } - return result; - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/Scheme.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/Scheme.java deleted file mode 100644 index a40e1ee164..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/Scheme.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import java.util.List; - -class Scheme { - public static final String NEO4J_URI_SCHEME = "neo4j"; - public static final String NEO4J_HIGH_TRUST_URI_SCHEME = "neo4j+s"; - public static final String NEO4J_LOW_TRUST_URI_SCHEME = "neo4j+ssc"; - - static boolean isRoutingScheme(String scheme) { - return List.of(NEO4J_LOW_TRUST_URI_SCHEME, NEO4J_HIGH_TRUST_URI_SCHEME, NEO4J_URI_SCHEME) - .contains(scheme); - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/SecurityPlan.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/SecurityPlan.java deleted file mode 100644 index c8dd62d609..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/SecurityPlan.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import javax.net.ssl.SSLContext; - -/** - * A SecurityPlan consists of encryption and trust details. - */ -public interface SecurityPlan { - - @SuppressWarnings("SameReturnValue") - boolean requiresEncryption(); - - @SuppressWarnings("SameReturnValue") - boolean requiresClientAuth(); - - SSLContext sslContext(); - - boolean requiresHostnameVerification(); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/SecurityPlanImpl.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/SecurityPlanImpl.java deleted file mode 100644 index c2931a8b57..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/SecurityPlanImpl.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import javax.net.ssl.SSLContext; - -/** - * A SecurityPlan consists of encryption and trust details. - */ -record SecurityPlanImpl( - boolean requiresEncryption, - boolean requiresClientAuth, - SSLContext sslContext, - boolean requiresHostnameVerification) - implements SecurityPlan {} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/SecurityPlans.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/SecurityPlans.java deleted file mode 100644 index 4ffc4dbd60..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/SecurityPlans.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import java.io.IOException; -import java.security.GeneralSecurityException; -import javax.net.ssl.KeyManager; -import javax.net.ssl.SSLContext; -import org.neo4j.driver.internal.bolt.api.ssl.RevocationCheckingStrategy; -import org.neo4j.driver.internal.bolt.api.ssl.SSLContexts; -import org.neo4j.driver.internal.bolt.api.ssl.TrustManagerFactories; - -public final class SecurityPlans { - private static final SecurityPlan UNENCRYPTED = new SecurityPlanImpl(false, false, null, false); - - public static SecurityPlan encrypted( - boolean requiresClientAuth, SSLContext sslContext, boolean requiresHostnameVerification) { - return new SecurityPlanImpl(true, requiresClientAuth, sslContext, requiresHostnameVerification); - } - - public static SecurityPlan encryptedForAnyCertificate() throws GeneralSecurityException { - var sslContext = SSLContexts.forAnyCertificate(new KeyManager[0]); - return encrypted(false, sslContext, false); - } - - public static SecurityPlan encryptedForSystemCASignedCertificates() throws GeneralSecurityException, IOException { - var trustManagerFactory = TrustManagerFactories.forSystemCertificates(RevocationCheckingStrategy.NO_CHECKS); - var sslContext = SSLContexts.forTrustManagers(new KeyManager[0], trustManagerFactory.getTrustManagers()); - return encrypted(false, sslContext, true); - } - - public static SecurityPlan unencrypted() { - return UNENCRYPTED; - } - - private SecurityPlans() {} -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/SummaryCounters.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/SummaryCounters.java deleted file mode 100644 index 8dbbd98bbb..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/SummaryCounters.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -/** - * Contains counters for various operations that a query triggered. - * - * @author Neo4j Drivers Team - * @since 1.0.0 - */ -public interface SummaryCounters { - - int totalCount(); - - /** - * Whether there were any updates at all, eg. any of the counters are greater than 0. - * @return true if the query made any updates - */ - boolean containsUpdates(); - - /** - * Returns the number of nodes created. - * @return number of nodes created. - */ - int nodesCreated(); - - /** - * Returns the number of nodes deleted. - * @return number of nodes deleted. - */ - int nodesDeleted(); - - /** - * Returns the number of relationships created. - * @return number of relationships created. - */ - int relationshipsCreated(); - - /** - * Returns the number of relationships deleted. - * @return number of relationships deleted. - */ - int relationshipsDeleted(); - - /** - * Returns the number of properties (on both nodes and relationships) set. - * @return number of properties (on both nodes and relationships) set. - */ - int propertiesSet(); - - /** - * Returns the number of labels added to nodes. - * @return number of labels added to nodes. - */ - int labelsAdded(); - - /** - * Returns the number of labels removed from nodes. - * @return number of labels removed from nodes. - */ - int labelsRemoved(); - - /** - * Returns the number of indexes added to the schema. - * @return number of indexes added to the schema. - */ - int indexesAdded(); - - /** - * Returns the number of indexes removed from the schema. - * @return number of indexes removed from the schema. - */ - int indexesRemoved(); - - /** - * Returns the number of constraints added to the schema. - * @return number of constraints added to the schema. - */ - int constraintsAdded(); - - /** - * Returns the number of constraints removed from the schema. - * @return number of constraints removed from the schema. - */ - int constraintsRemoved(); - - /** - * If the query updated the system graph in any way, this method will return true. - * @return true if the system graph has been updated. - */ - boolean containsSystemUpdates(); - - /** - * Returns the number of system updates performed by this query. - * @return the number of system updates performed by this query. - */ - int systemUpdates(); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/TelemetryApi.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/TelemetryApi.java deleted file mode 100644 index 0da5db6773..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/TelemetryApi.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -/** - * An enum of valid telemetry metrics. - */ -public enum TelemetryApi { - MANAGED_TRANSACTION(0), - UNMANAGED_TRANSACTION(1), - AUTO_COMMIT_TRANSACTION(2), - EXECUTABLE_QUERY(3); - - private final Integer value; - - TelemetryApi(Integer value) { - this.value = value; - } - - public Integer getValue() { - return value; - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/TransactionType.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/TransactionType.java deleted file mode 100644 index 6249bdfea5..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/TransactionType.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -public enum TransactionType { - DEFAULT, - UNCONSTRAINED -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltClientException.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltClientException.java deleted file mode 100644 index 0968fd3863..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltClientException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.exception; - -import java.io.Serial; - -public class BoltClientException extends BoltException { - @Serial - private static final long serialVersionUID = -5218004917132451861L; - - public BoltClientException(String message) { - super(message); - } - - public BoltClientException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltConnectionAcquisitionException.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltConnectionAcquisitionException.java deleted file mode 100644 index 7ef8e5cc86..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltConnectionAcquisitionException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.exception; - -import java.io.Serial; - -public class BoltConnectionAcquisitionException extends BoltException { - @Serial - private static final long serialVersionUID = -5218004917132451861L; - - public BoltConnectionAcquisitionException(String message) { - super(message); - } - - public BoltConnectionAcquisitionException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltConnectionReadTimeoutException.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltConnectionReadTimeoutException.java deleted file mode 100644 index b0ddd59f49..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltConnectionReadTimeoutException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.exception; - -import java.io.Serial; - -public class BoltConnectionReadTimeoutException extends BoltServiceUnavailableException { - @Serial - private static final long serialVersionUID = -5218004917132451861L; - - public BoltConnectionReadTimeoutException(String message) { - super(message); - } - - public BoltConnectionReadTimeoutException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltDiscoveryException.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltDiscoveryException.java deleted file mode 100644 index 9478cfd86e..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltDiscoveryException.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.exception; - -import java.io.Serial; - -public class BoltDiscoveryException extends BoltException { - @Serial - private static final long serialVersionUID = -177641311561760099L; - - public BoltDiscoveryException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltException.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltException.java deleted file mode 100644 index 9f09b02fbb..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.exception; - -import java.io.Serial; - -public class BoltException extends RuntimeException { - @Serial - private static final long serialVersionUID = -5218004917132451861L; - - public BoltException(String message) { - super(message); - } - - public BoltException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltFailureException.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltFailureException.java deleted file mode 100644 index 309e404f89..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltFailureException.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.exception; - -import java.io.Serial; -import java.util.Map; -import java.util.Objects; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public class BoltFailureException extends BoltGqlErrorException { - @Serial - private static final long serialVersionUID = -1731084000671105197L; - - private final String code; - - public BoltFailureException( - String code, - String message, - String gqlStatus, - String statusDescription, - Map diagnosticRecord, - Throwable cause) { - super(message, gqlStatus, statusDescription, diagnosticRecord, cause); - this.code = Objects.requireNonNull(code); - } - - public String code() { - return code; - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltGqlErrorException.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltGqlErrorException.java deleted file mode 100644 index a8fde2d18e..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltGqlErrorException.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.exception; - -import java.io.Serial; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public class BoltGqlErrorException extends BoltException { - @Serial - private static final long serialVersionUID = -1731084000671105197L; - - private final String gqlStatus; - private final String statusDescription; - private final Map diagnosticRecord; - - public BoltGqlErrorException( - String message, - String gqlStatus, - String statusDescription, - Map diagnosticRecord, - Throwable cause) { - super(message, cause); - this.gqlStatus = Objects.requireNonNull(gqlStatus); - this.statusDescription = Objects.requireNonNull(statusDescription); - this.diagnosticRecord = Objects.requireNonNull(diagnosticRecord); - } - - public String gqlStatus() { - return gqlStatus; - } - - public String statusDescription() { - return statusDescription; - } - - public Map diagnosticRecord() { - return diagnosticRecord; - } - - public Optional gqlCause() { - return findFirstGqlCause(this, BoltGqlErrorException.class); - } - - @SuppressWarnings("DuplicatedCode") - private static Optional findFirstGqlCause(Throwable throwable, Class targetCls) { - var cause = throwable.getCause(); - if (cause == null) { - return Optional.empty(); - } - if (cause.getClass().isAssignableFrom(targetCls)) { - return Optional.of(targetCls.cast(cause)); - } else { - return findFirstGqlCause(cause, targetCls); - } - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltProtocolException.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltProtocolException.java deleted file mode 100644 index 113632f5df..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltProtocolException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.exception; - -import java.io.Serial; - -public class BoltProtocolException extends BoltException { - @Serial - private static final long serialVersionUID = 7170273806952291048L; - - public BoltProtocolException(String message) { - super(message); - } - - public BoltProtocolException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltServiceUnavailableException.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltServiceUnavailableException.java deleted file mode 100644 index 6faae2eb2d..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltServiceUnavailableException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.exception; - -import java.io.Serial; - -public class BoltServiceUnavailableException extends BoltException { - @Serial - private static final long serialVersionUID = 1108615355108108484L; - - public BoltServiceUnavailableException(String message) { - super(message); - } - - public BoltServiceUnavailableException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltTransientException.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltTransientException.java deleted file mode 100644 index cd06b84188..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltTransientException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.exception; - -import java.io.Serial; - -public class BoltTransientException extends BoltException { - @Serial - private static final long serialVersionUID = -1731084000671105197L; - - public BoltTransientException(String message) { - super(message); - } - - public BoltTransientException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltUnsupportedFeatureException.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltUnsupportedFeatureException.java deleted file mode 100644 index 860c8ba8cb..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltUnsupportedFeatureException.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.exception; - -import java.io.Serial; - -public class BoltUnsupportedFeatureException extends BoltException { - @Serial - private static final long serialVersionUID = 5397629610198032003L; - - public BoltUnsupportedFeatureException(String message) { - super(message); - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltUntrustedServerException.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltUntrustedServerException.java deleted file mode 100644 index 2609f78de1..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/BoltUntrustedServerException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.exception; - -import java.io.Serial; - -public class BoltUntrustedServerException extends BoltException { - @Serial - private static final long serialVersionUID = -5218004917132451861L; - - public BoltUntrustedServerException(String message) { - super(message); - } - - public BoltUntrustedServerException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/MinVersionAcquisitionException.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/MinVersionAcquisitionException.java deleted file mode 100644 index b6be98b9e6..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/exception/MinVersionAcquisitionException.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.exception; - -import java.io.Serial; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; - -public class MinVersionAcquisitionException extends BoltException { - @Serial - private static final long serialVersionUID = 2620821821322630443L; - - private final BoltProtocolVersion version; - - public MinVersionAcquisitionException(String message, BoltProtocolVersion version) { - super(message); - this.version = version; - } - - public BoltProtocolVersion version() { - return version; - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ssl/CertificateTool.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ssl/CertificateTool.java deleted file mode 100644 index 253b3527dd..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ssl/CertificateTool.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.ssl; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.List; - -/** - * A tool used to certs. - */ -final class CertificateTool { - /** - * Load the certificates written in X.509 format in a file to a key store. - * - * @param certFiles the certificate files - * @param keyStore the key store - */ - public static void loadX509Cert(List certFiles, KeyStore keyStore) - throws GeneralSecurityException, IOException { - var certCount = 0; // The files might contain multiple certs - for (var certFile : certFiles) { - try (var inputStream = new BufferedInputStream(new FileInputStream(certFile))) { - var certFactory = CertificateFactory.getInstance("X.509"); - - while (inputStream.available() > 0) { - try { - var cert = certFactory.generateCertificate(inputStream); - certCount++; - loadX509Cert(cert, "neo4j.javadriver.trustedcert." + certCount, keyStore); - } catch (CertificateException e) { - if (e.getCause() != null && e.getCause().getMessage().equals("Empty input")) { - // This happens if there is whitespace at the end of the certificate - we load one cert, and - // then try and load a - // second cert, at which point we fail - return; - } - throw new IOException( - "Failed to load certificate from `" + certFile.getAbsolutePath() + "`: " + certCount - + " : " + e.getMessage(), - e); - } - } - } - } - } - - public static void loadX509Cert(X509Certificate[] certificates, KeyStore keyStore) throws GeneralSecurityException { - for (var i = 0; i < certificates.length; i++) { - loadX509Cert(certificates[i], "neo4j.javadriver.trustedcert." + i, keyStore); - } - } - - private static void loadX509Cert(Certificate cert, String certAlias, KeyStore keyStore) throws KeyStoreException { - keyStore.setCertificateEntry(certAlias, cert); - } - - private CertificateTool() {} -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ssl/RevocationCheckingStrategy.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ssl/RevocationCheckingStrategy.java deleted file mode 100644 index 8003008c4d..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ssl/RevocationCheckingStrategy.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.ssl; - -public enum RevocationCheckingStrategy { - /** Don't do any OCSP revocation checks, regardless whether there are stapled revocation statuses or not. */ - NO_CHECKS, - /** Verify OCSP revocation checks when the revocation status is stapled to the certificate, continue if not. */ - VERIFY_IF_PRESENT, - /** Require stapled revocation status and verify OCSP revocation checks, fail if no revocation status is stapled to the certificate. */ - STRICT; - - /** - * Returns whether a given strategy requires revocation checking. - * @param revocationCheckingStrategy the strategy - * @return whether revocation checking is required - */ - static boolean requiresRevocationChecking(RevocationCheckingStrategy revocationCheckingStrategy) { - return revocationCheckingStrategy.equals(STRICT) || revocationCheckingStrategy.equals(VERIFY_IF_PRESENT); - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ssl/SSLContexts.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ssl/SSLContexts.java deleted file mode 100644 index 2128c1c4fc..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ssl/SSLContexts.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.ssl; - -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import javax.net.ssl.KeyManager; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; - -public final class SSLContexts { - - public static SSLContext forAnyCertificate(KeyManager[] keyManagers) - throws NoSuchAlgorithmException, KeyManagementException { - return forTrustManagers(keyManagers, new TrustManager[] {new TrustAllTrustManager()}); - } - - public static SSLContext forTrustManagers(KeyManager[] keyManagers, TrustManager[] trustManagers) - throws NoSuchAlgorithmException, KeyManagementException { - var sslContext = SSLContext.getInstance("TLS"); - sslContext.init(keyManagers, trustManagers, null); - return sslContext; - } - - private SSLContexts() {} -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ssl/TrustAllTrustManager.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ssl/TrustAllTrustManager.java deleted file mode 100644 index f95c2b3cac..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ssl/TrustAllTrustManager.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.ssl; - -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import javax.net.ssl.X509TrustManager; - -final class TrustAllTrustManager implements X509TrustManager { - public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { - throw new CertificateException("All client connections to this client are forbidden."); - } - - public void checkServerTrusted(X509Certificate[] chain, String authType) { - // all fine, pass through - } - - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ssl/TrustManagerFactories.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ssl/TrustManagerFactories.java deleted file mode 100644 index ae5b27ec02..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/ssl/TrustManagerFactories.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.ssl; - -import static org.neo4j.driver.internal.bolt.api.ssl.CertificateTool.loadX509Cert; -import static org.neo4j.driver.internal.bolt.api.ssl.RevocationCheckingStrategy.VERIFY_IF_PRESENT; -import static org.neo4j.driver.internal.bolt.api.ssl.RevocationCheckingStrategy.requiresRevocationChecking; - -import java.io.File; -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.InvalidAlgorithmParameterException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.Security; -import java.security.cert.CertificateException; -import java.security.cert.PKIXBuilderParameters; -import java.security.cert.X509CertSelector; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import javax.net.ssl.CertPathTrustManagerParameters; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; - -public final class TrustManagerFactories { - - public static TrustManagerFactory forSystemCertificates(RevocationCheckingStrategy revocationCheckingStrategy) - throws GeneralSecurityException, IOException { - return configureTrustManagerFactory(Collections.emptyList(), revocationCheckingStrategy); - } - - public static TrustManagerFactory forCertificates( - List files, RevocationCheckingStrategy revocationCheckingStrategy) - throws GeneralSecurityException, IOException { - return configureTrustManagerFactory(files, revocationCheckingStrategy); - } - - private static TrustManagerFactory configureTrustManagerFactory( - List customCertFiles, RevocationCheckingStrategy revocationCheckingStrategy) - throws GeneralSecurityException, IOException { - var trustedKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); - trustedKeyStore.load(null, null); - - if (!customCertFiles.isEmpty()) { - // Certificate files are specified, so we will load the certificates in the file - loadX509Cert(customCertFiles, trustedKeyStore); - } else { - loadSystemCertificates(trustedKeyStore); - } - - var pkixBuilderParameters = configurePKIXBuilderParameters(trustedKeyStore, revocationCheckingStrategy); - - var trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - - if (pkixBuilderParameters == null) { - trustManagerFactory.init(trustedKeyStore); - } else { - trustManagerFactory.init(new CertPathTrustManagerParameters(pkixBuilderParameters)); - } - return trustManagerFactory; - } - - private static PKIXBuilderParameters configurePKIXBuilderParameters( - KeyStore trustedKeyStore, RevocationCheckingStrategy revocationCheckingStrategy) - throws InvalidAlgorithmParameterException, KeyStoreException { - PKIXBuilderParameters pkixBuilderParameters = null; - - if (requiresRevocationChecking(revocationCheckingStrategy)) { - // Configure certificate revocation checking (X509CertSelector() selects all certificates) - pkixBuilderParameters = new PKIXBuilderParameters(trustedKeyStore, new X509CertSelector()); - - // sets checking of stapled ocsp response - pkixBuilderParameters.setRevocationEnabled(true); - - // enables status_request extension in client hello - System.setProperty("jdk.tls.client.enableStatusRequestExtension", "true"); - - if (revocationCheckingStrategy.equals(VERIFY_IF_PRESENT)) { - // enables soft-fail behaviour if no stapled response found. - Security.setProperty("ocsp.enable", "true"); - } - } - return pkixBuilderParameters; - } - - private static void loadSystemCertificates(KeyStore trustedKeyStore) throws GeneralSecurityException { - // To customize the PKIXParameters we need to get hold of the default KeyStore, no other elegant way available - var tempFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - tempFactory.init((KeyStore) null); - - // Get hold of the default trust manager - var x509TrustManager = (X509TrustManager) Arrays.stream(tempFactory.getTrustManagers()) - .filter(trustManager -> trustManager instanceof X509TrustManager) - .findFirst() - .orElse(null); - - if (x509TrustManager == null) { - throw new CertificateException("No system certificates found"); - } else { - // load system default certificates into KeyStore - loadX509Cert(x509TrustManager.getAcceptedIssuers(), trustedKeyStore); - } - } - - private TrustManagerFactories() {} -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/BeginSummary.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/BeginSummary.java deleted file mode 100644 index fbeef2f007..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/BeginSummary.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.summary; - -import java.util.Optional; - -public interface BeginSummary { - Optional databaseName(); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/CommitSummary.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/CommitSummary.java deleted file mode 100644 index e9c04bab41..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/CommitSummary.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.summary; - -import java.util.Optional; - -public interface CommitSummary { - Optional bookmark(); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/DiscardSummary.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/DiscardSummary.java deleted file mode 100644 index 10a186c3a6..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/DiscardSummary.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.summary; - -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public interface DiscardSummary { - Map metadata(); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/LogoffSummary.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/LogoffSummary.java deleted file mode 100644 index d8b788988b..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/LogoffSummary.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.summary; - -public interface LogoffSummary {} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/LogonSummary.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/LogonSummary.java deleted file mode 100644 index 43a81e8faf..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/LogonSummary.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.summary; - -public interface LogonSummary {} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/PullSummary.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/PullSummary.java deleted file mode 100644 index e2ddd21683..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/PullSummary.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.summary; - -import java.util.Map; -import org.neo4j.driver.internal.bolt.api.values.Value; - -public interface PullSummary { - @SuppressWarnings("SameReturnValue") - boolean hasMore(); - - Map metadata(); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/ResetSummary.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/ResetSummary.java deleted file mode 100644 index 5f68153bc5..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/ResetSummary.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.summary; - -public interface ResetSummary {} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/RollbackSummary.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/RollbackSummary.java deleted file mode 100644 index ea5cb0dcfa..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/RollbackSummary.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.summary; - -public interface RollbackSummary {} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/RouteSummary.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/RouteSummary.java deleted file mode 100644 index 72e080ec3f..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/RouteSummary.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.summary; - -import org.neo4j.driver.internal.bolt.api.ClusterComposition; - -public interface RouteSummary { - ClusterComposition clusterComposition(); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/RunSummary.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/RunSummary.java deleted file mode 100644 index 3716f9adca..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/RunSummary.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.summary; - -import java.util.List; -import java.util.Optional; - -public interface RunSummary { - long queryId(); - - List keys(); - - long resultAvailableAfter(); - - Optional databaseName(); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/TelemetrySummary.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/TelemetrySummary.java deleted file mode 100644 index 9c834e9408..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/summary/TelemetrySummary.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.summary; - -public interface TelemetrySummary {} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/IsoDuration.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/IsoDuration.java deleted file mode 100644 index 99aeea15e0..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/IsoDuration.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.values; - -public interface IsoDuration { - long months(); - - long days(); - - long seconds(); - - int nanoseconds(); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/MapAccessor.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/MapAccessor.java deleted file mode 100644 index 0d2f6c28cf..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/MapAccessor.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.values; - -import java.util.Map; -import java.util.function.Function; - -interface MapAccessor { - Iterable keys(); - - int size(); - - Value get(String key); - - Iterable values(); - - boolean containsKey(String key); - - Map asMap(Function mapFunction); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/Node.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/Node.java deleted file mode 100644 index a2b7bbc39a..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/Node.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.values; - -public interface Node { - long id(); - - String elementId(); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/Path.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/Path.java deleted file mode 100644 index 965a0ae414..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/Path.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.values; - -public interface Path {} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/Point.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/Point.java deleted file mode 100644 index f5d333ae6b..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/Point.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.values; - -public interface Point { - int srid(); - - double x(); - - double y(); - - @SuppressWarnings("SameReturnValue") - double z(); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/Relationship.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/Relationship.java deleted file mode 100644 index 6f83fcb2bd..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/Relationship.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.values; - -public interface Relationship { - void setStartAndEnd(long start, String startElementId, long end, String endElementId); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/Segment.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/Segment.java deleted file mode 100644 index 112043f552..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/Segment.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.values; - -public interface Segment {} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/Type.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/Type.java deleted file mode 100644 index bbf52ab51b..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/Type.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.values; - -public enum Type { - ANY, - BOOLEAN, - BYTES, - STRING, - NUMBER, - INTEGER, - FLOAT, - LIST, - MAP, - NODE, - RELATIONSHIP, - PATH, - POINT, - DATE, - TIME, - LOCAL_TIME, - LOCAL_DATE_TIME, - DATE_TIME, - DURATION, - NULL -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/Value.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/Value.java deleted file mode 100644 index dd1146e757..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/Value.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.values; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZonedDateTime; - -public interface Value extends MapAccessor { - Type type(); - - boolean asBoolean(); - - byte[] asByteArray(); - - String asString(); - - long asLong(); - - double asDouble(); - - LocalDate asLocalDate(); - - OffsetTime asOffsetTime(); - - LocalTime asLocalTime(); - - LocalDateTime asLocalDateTime(); - - ZonedDateTime asZonedDateTime(); - - IsoDuration asIsoDuration(); - - Point asPoint(); - - boolean isNull(); - - boolean isEmpty(); -} diff --git a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/ValueFactory.java b/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/ValueFactory.java deleted file mode 100644 index 2f55486e05..0000000000 --- a/bolt-api/src/main/java/org/neo4j/driver/internal/bolt/api/values/ValueFactory.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.values; - -import java.time.DateTimeException; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -public interface ValueFactory { - Value value(Object value); - - Node node(long id, String elementId, Collection labels, Map properties); - - Relationship relationship( - long id, - String elementId, - long start, - String startElementId, - long end, - String endElementId, - String type, - Map properties); - - Segment segment(Node start, Relationship relationship, Node end); - - Path path(List segments, List nodes, List relationships); - - Value isoDuration(long months, long days, long seconds, int nanoseconds); - - Value point(int srid, double x, double y); - - Value point(int srid, double x, double y, double z); - - Value unsupportedDateTimeValue(DateTimeException e); -} diff --git a/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/BoltAgentUtil.java b/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/BoltAgentUtil.java deleted file mode 100644 index 837fdf6599..0000000000 --- a/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/BoltAgentUtil.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -public interface BoltAgentUtil { - BoltAgent VALUE = new BoltAgent("agent", null, null, null); -} diff --git a/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/BoltServerAddressParsingTest.java b/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/BoltServerAddressParsingTest.java deleted file mode 100644 index 9e3f55be59..0000000000 --- a/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/BoltServerAddressParsingTest.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.neo4j.driver.internal.bolt.api.BoltServerAddress.DEFAULT_PORT; - -import java.util.stream.Stream; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -class BoltServerAddressParsingTest { - private static Stream addressesToParse() { - return Stream.of( - // Hostname - Arguments.of("localhost", "localhost", DEFAULT_PORT), - Arguments.of("localhost:9193", "localhost", 9193), - Arguments.of("neo4j.com", "neo4j.com", DEFAULT_PORT), - Arguments.of("royal-server.com.uk", "royal-server.com.uk", DEFAULT_PORT), - Arguments.of("royal-server.com.uk:4546", "royal-server.com.uk", 4546), - - // Hostname with scheme - Arguments.of("bolt://localhost", "localhost", DEFAULT_PORT), - Arguments.of("neo4j://localhost", "localhost", DEFAULT_PORT), - Arguments.of("bolt://localhost:9193", "localhost", 9193), - Arguments.of("neo4j://localhost:9193", "localhost", 9193), - Arguments.of("bolt://neo4j.com", "neo4j.com", DEFAULT_PORT), - Arguments.of("neo4j://neo4j.com", "neo4j.com", DEFAULT_PORT), - Arguments.of("bolt://royal-server.com.uk", "royal-server.com.uk", DEFAULT_PORT), - Arguments.of("neo4j://royal-server.com.uk", "royal-server.com.uk", DEFAULT_PORT), - Arguments.of("bolt://royal-server.com.uk:4546", "royal-server.com.uk", 4546), - Arguments.of("neo4j://royal-server.com.uk:4546", "royal-server.com.uk", 4546), - - // IPv4 - Arguments.of("127.0.0.1", "127.0.0.1", DEFAULT_PORT), - Arguments.of("8.8.8.8:8080", "8.8.8.8", 8080), - Arguments.of("0.0.0.0", "0.0.0.0", DEFAULT_PORT), - Arguments.of("192.0.2.235:4329", "192.0.2.235", 4329), - Arguments.of("172.31.255.255:255", "172.31.255.255", 255), - - // IPv4 with scheme - Arguments.of("bolt://198.51.100.0", "198.51.100.0", DEFAULT_PORT), - Arguments.of("bolt://65.21.10.12:5656", "65.21.10.12", 5656), - Arguments.of("neo4j://12.0.0.5", "12.0.0.5", DEFAULT_PORT), - Arguments.of("neo4j://155.55.20.6:9191", "155.55.20.6", 9191), - - // IPv6 - Arguments.of("::1", "[::1]", DEFAULT_PORT), - Arguments.of("ff02::2:ff00:0", "[ff02::2:ff00:0]", DEFAULT_PORT), - Arguments.of("[1afc:0:a33:85a3::ff2f]", "[1afc:0:a33:85a3::ff2f]", DEFAULT_PORT), - Arguments.of("[::1]:1515", "[::1]", 1515), - Arguments.of("[ff0a::101]:8989", "[ff0a::101]", 8989), - - // IPv6 with scheme - Arguments.of("bolt://[::1]", "[::1]", DEFAULT_PORT), - Arguments.of("neo4j://[::1]", "[::1]", DEFAULT_PORT), - Arguments.of("bolt://[ff02::d]", "[ff02::d]", DEFAULT_PORT), - Arguments.of("neo4j://[fe80::b279:2f]", "[fe80::b279:2f]", DEFAULT_PORT), - Arguments.of("bolt://[::1]:8687", "[::1]", 8687), - Arguments.of("neo4j://[::1]:1212", "[::1]", 1212), - Arguments.of("bolt://[ff02::d]:9090", "[ff02::d]", 9090), - Arguments.of("neo4j://[fe80::b279:2f]:7878", "[fe80::b279:2f]", 7878), - - // IPv6 with zone id - Arguments.of("::1%eth0", "[::1%eth0]", DEFAULT_PORT), - Arguments.of("ff02::2:ff00:0%12", "[ff02::2:ff00:0%12]", DEFAULT_PORT), - Arguments.of("[1afc:0:a33:85a3::ff2f%eth1]", "[1afc:0:a33:85a3::ff2f%eth1]", DEFAULT_PORT), - Arguments.of("[::1%eth0]:3030", "[::1%eth0]", 3030), - Arguments.of("[ff0a::101%8]:4040", "[ff0a::101%8]", 4040), - - // IPv6 with scheme and zone id - Arguments.of("bolt://[::1%eth5]", "[::1%eth5]", DEFAULT_PORT), - Arguments.of("neo4j://[::1%12]", "[::1%12]", DEFAULT_PORT), - Arguments.of("bolt://[ff02::d%3]", "[ff02::d%3]", DEFAULT_PORT), - Arguments.of("neo4j://[fe80::b279:2f%eth0]", "[fe80::b279:2f%eth0]", DEFAULT_PORT), - Arguments.of("bolt://[::1%eth3]:8687", "[::1%eth3]", 8687), - Arguments.of("neo4j://[::1%2]:1212", "[::1%2]", 1212), - Arguments.of("bolt://[ff02::d%3]:9090", "[ff02::d%3]", 9090), - Arguments.of("neo4j://[fe80::b279:2f%eth1]:7878", "[fe80::b279:2f%eth1]", 7878)); - } - - @ParameterizedTest - @MethodSource("addressesToParse") - void shouldParseAddress(String address, String expectedHost, int expectedPort) { - var parsed = new BoltServerAddress(address); - assertEquals(expectedHost, parsed.host()); - assertEquals(expectedPort, parsed.port()); - } -} diff --git a/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/BoltServerAddressTest.java b/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/BoltServerAddressTest.java deleted file mode 100644 index 1d37e47e71..0000000000 --- a/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/BoltServerAddressTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.neo4j.driver.internal.bolt.api.BoltServerAddress.DEFAULT_PORT; - -import java.net.URI; -import org.junit.jupiter.api.Test; - -class BoltServerAddressTest { - @Test - void defaultPortShouldBe7687() { - assertEquals(7687, DEFAULT_PORT); - } - - @Test - void portShouldUseDefaultIfNotSupplied() { - assertEquals(BoltServerAddress.DEFAULT_PORT, new BoltServerAddress("localhost").port()); - } - - @Test - void shouldHaveCorrectToString() { - assertEquals("localhost:4242", new BoltServerAddress("localhost", 4242).toString()); - assertEquals("127.0.0.1:8888", new BoltServerAddress("127.0.0.1", 8888).toString()); - } - - @Test - void shouldVerifyHost() { - assertThrows(NullPointerException.class, () -> new BoltServerAddress(null, 0)); - } - - @Test - void shouldVerifyPort() { - assertThrows(IllegalArgumentException.class, () -> new BoltServerAddress("localhost", -1)); - assertThrows(IllegalArgumentException.class, () -> new BoltServerAddress("localhost", -42)); - assertThrows(IllegalArgumentException.class, () -> new BoltServerAddress("localhost", 65_536)); - assertThrows(IllegalArgumentException.class, () -> new BoltServerAddress("localhost", 99_999)); - } - - @Test - void shouldUseUriWithHostButWithoutPort() { - var uri = URI.create("bolt://neo4j.com"); - var address = new BoltServerAddress(uri); - - assertEquals("neo4j.com", address.host()); - assertEquals(DEFAULT_PORT, address.port()); - } - - @Test - void shouldUseUriWithHostAndPort() { - var uri = URI.create("bolt://neo4j.com:12345"); - var address = new BoltServerAddress(uri); - - assertEquals("neo4j.com", address.host()); - assertEquals(12345, address.port()); - } - - @Test - void shouldIncludeHostAndPortInToString() { - var address = new BoltServerAddress("localhost", 8081); - assertEquals("localhost:8081", address.toString()); - } -} diff --git a/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/ClusterCompositionTest.java b/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/ClusterCompositionTest.java deleted file mode 100644 index c2dc2a484f..0000000000 --- a/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/ClusterCompositionTest.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import static java.util.Arrays.asList; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.neo4j.driver.internal.bolt.api.util.ClusterCompositionUtil.A; -import static org.neo4j.driver.internal.bolt.api.util.ClusterCompositionUtil.B; -import static org.neo4j.driver.internal.bolt.api.util.ClusterCompositionUtil.C; -import static org.neo4j.driver.internal.bolt.api.util.ClusterCompositionUtil.D; -import static org.neo4j.driver.internal.bolt.api.util.ClusterCompositionUtil.E; -import static org.neo4j.driver.internal.bolt.api.util.ClusterCompositionUtil.F; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import org.junit.jupiter.api.Test; - -class ClusterCompositionTest { - @Test - void hasWritersReturnsFalseWhenNoWriters() { - var composition = newComposition(1, addresses(A, B), addresses(), addresses(C, D)); - - assertFalse(composition.hasWriters()); - } - - @Test - void hasWritersReturnsTrueWhenSomeWriters() { - var composition = newComposition(1, addresses(A, B), addresses(C, D), addresses(E, F)); - - assertTrue(composition.hasWriters()); - } - - @Test - void hasRoutersAndReadersReturnsFalseWhenNoRouters() { - var composition = newComposition(1, addresses(A, B), addresses(C, D), addresses()); - - assertFalse(composition.hasRoutersAndReaders()); - } - - @Test - void hasRoutersAndReadersReturnsFalseWhenNoReaders() { - var composition = newComposition(1, addresses(), addresses(A, B), addresses(C, D)); - - assertFalse(composition.hasRoutersAndReaders()); - } - - @Test - void hasRoutersAndReadersWhenSomeReadersAndRouters() { - var composition = newComposition(1, addresses(A, B), addresses(C, D), addresses(E, F)); - - assertTrue(composition.hasRoutersAndReaders()); - } - - @Test - void readersWhenEmpty() { - var composition = newComposition(1, addresses(), addresses(A, B), addresses(C, D)); - - assertEquals(0, composition.readers().size()); - } - - @Test - void writersWhenEmpty() { - var composition = newComposition(1, addresses(A, B), addresses(), addresses(C, D)); - - assertEquals(0, composition.writers().size()); - } - - @Test - void routersWhenEmpty() { - var composition = newComposition(1, addresses(A, B), addresses(C, D), addresses()); - - assertEquals(0, composition.routers().size()); - } - - @Test - void readersWhenNonEmpty() { - var composition = newComposition(1, addresses(A, B), addresses(C, D), addresses(E, F)); - - assertEquals(addresses(A, B), composition.readers()); - } - - @Test - void writersWhenNonEmpty() { - var composition = newComposition(1, addresses(A, B), addresses(C, D), addresses(E, F)); - - assertEquals(addresses(C, D), composition.writers()); - } - - @Test - void routersWhenNonEmpty() { - var composition = newComposition(1, addresses(A, B), addresses(C, D), addresses(E, F)); - - assertEquals(addresses(E, F), composition.routers()); - } - - @Test - void expirationTimestamp() { - var composition = newComposition(42, addresses(A, B), addresses(C, D), addresses(E, F)); - - assertEquals(42, composition.expirationTimestamp()); - } - - private static ClusterComposition newComposition( - long expirationTimestamp, - Set readers, - Set writers, - Set routers) { - return new ClusterComposition(expirationTimestamp, readers, writers, routers, null); - } - - private static Set addresses(BoltServerAddress... elements) { - return new LinkedHashSet<>(asList(elements)); - } - - private static Map serversEntry(String role, BoltServerAddress... addresses) { - Map map = new HashMap<>(); - map.put("role", role); - var addressStrings = - Arrays.stream(addresses).map(BoltServerAddress::toString).collect(Collectors.toList()); - map.put("addresses", addressStrings); - return map; - } -} diff --git a/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/DatabaseNameUtilTest.java b/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/DatabaseNameUtilTest.java deleted file mode 100644 index e3fcbd2364..0000000000 --- a/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/DatabaseNameUtilTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.DEFAULT_DATABASE_NAME; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.SYSTEM_DATABASE_NAME; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.database; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.systemDatabase; - -import org.junit.jupiter.api.Test; - -class DatabaseNameUtilTest { - @Test - @SuppressWarnings("EqualsWithItself") - void shouldDatabaseNameBeEqual() { - assertEquals(defaultDatabase(), defaultDatabase()); - assertEquals(defaultDatabase(), database(null)); - assertEquals(defaultDatabase(), database(DEFAULT_DATABASE_NAME)); - - assertEquals(systemDatabase(), systemDatabase()); - assertEquals(systemDatabase(), database("system")); - assertEquals(systemDatabase(), database(SYSTEM_DATABASE_NAME)); - - assertEquals(database("hello"), database("hello")); - } - - @Test - void shouldReturnDatabaseNameInDescription() { - assertEquals("", defaultDatabase().description()); - assertEquals("system", systemDatabase().description()); - assertEquals("hello", database("hello").description()); - } -} diff --git a/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/RoutingContextTest.java b/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/RoutingContextTest.java deleted file mode 100644 index 30ad5c17b9..0000000000 --- a/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/RoutingContextTest.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api; - -import static java.util.Collections.singletonMap; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.net.URI; -import java.util.HashMap; -import java.util.Map; -import org.junit.jupiter.api.Test; - -class RoutingContextTest { - @Test - void emptyContextIsNotDefined() { - assertFalse(RoutingContext.EMPTY.isDefined()); - } - - @Test - void emptyContextInEmptyMap() { - assertTrue(RoutingContext.EMPTY.toMap().isEmpty()); - } - - @Test - void uriWithoutQueryIsParsedToEmptyContext() { - testEmptyRoutingContext(URI.create("neo4j://localhost:7687/")); - } - - @Test - void uriWithEmptyQueryIsParsedToEmptyContext() { - testEmptyRoutingContext(URI.create("neo4j://localhost:7687?")); - testEmptyRoutingContext(URI.create("neo4j://localhost:7687/?")); - } - - @Test - void uriWithQueryIsParsed() { - var uri = URI.create("neo4j://localhost:7687/?key1=value1&key2=value2&key3=value3"); - var context = new RoutingContext(uri); - - assertTrue(context.isDefined()); - Map expectedMap = new HashMap<>(); - expectedMap.put("key1", "value1"); - expectedMap.put("key2", "value2"); - expectedMap.put("key3", "value3"); - expectedMap.put("address", "localhost:7687"); - assertEquals(expectedMap, context.toMap()); - } - - @Test - void boltUriDisablesServerSideRouting() { - var uri = URI.create("bolt://localhost:7687/?key1=value1&key2=value2&key3=value3"); - var context = new RoutingContext(uri); - - assertFalse(context.isServerRoutingEnabled()); - } - - @Test - void neo4jUriEnablesServerSideRouting() { - var uri = URI.create("neo4j://localhost:7687/?key1=value1&key2=value2&key3=value3"); - var context = new RoutingContext(uri); - - assertTrue(context.isServerRoutingEnabled()); - } - - @Test - void throwsForInvalidUriQuery() { - testIllegalUri(URI.create("neo4j://localhost:7687/?justKey")); - } - - @Test - void throwsForInvalidUriQueryKey() { - testIllegalUri(URI.create("neo4j://localhost:7687/?=value1&key2=value2")); - } - - @Test - void throwsForInvalidUriQueryValue() { - testIllegalUri(URI.create("neo4j://localhost:7687/key1?=value1&key2=")); - } - - @Test - void throwsForDuplicatedUriQueryParameters() { - testIllegalUri(URI.create("neo4j://localhost:7687/?key1=value1&key2=value2&key1=value2")); - } - - @Test - void mapRepresentationIsUnmodifiable() { - var uri = URI.create("neo4j://localhost:7687/?key1=value1"); - var context = new RoutingContext(uri); - - Map expectedMap = new HashMap<>(); - expectedMap.put("key1", "value1"); - expectedMap.put("address", "localhost:7687"); - - assertEquals(expectedMap, context.toMap()); - - assertThrows(UnsupportedOperationException.class, () -> context.toMap().put("key2", "value2")); - assertEquals(expectedMap, context.toMap()); - } - - @Test - void populateAddressWithDefaultPort() { - var uri = URI.create("neo4j://localhost/"); - var context = new RoutingContext(uri); - - assertEquals(singletonMap("address", "localhost:7687"), context.toMap()); - } - - @Test - void throwsExceptionIfAddressIsUsedInContext() { - var uri = URI.create("neo4j://localhost:7687/?key1=value1&address=someaddress:9010"); - - var e = assertThrows(IllegalArgumentException.class, () -> new RoutingContext(uri)); - assertEquals("The key 'address' is reserved for routing context.", e.getMessage()); - } - - private static void testIllegalUri(URI uri) { - assertThrows(IllegalArgumentException.class, () -> new RoutingContext(uri)); - } - - private static void testEmptyRoutingContext(URI uri) { - var context = new RoutingContext(uri); - - assertFalse(context.isDefined()); - assertEquals(singletonMap("address", "localhost:7687"), context.toMap()); - } -} diff --git a/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/ssl/CertificateToolTest.java b/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/ssl/CertificateToolTest.java deleted file mode 100644 index 019e8ca16f..0000000000 --- a/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/ssl/CertificateToolTest.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.ssl; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.math.BigInteger; -import java.security.GeneralSecurityException; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.KeyStore; -import java.security.NoSuchAlgorithmException; -import java.security.Provider; -import java.security.PublicKey; -import java.security.SecureRandom; -import java.security.Security; -import java.security.cert.Certificate; -import java.security.cert.CertificateEncodingException; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.Base64; -import java.util.Collections; -import java.util.Date; -import java.util.HashSet; -import java.util.Set; -import org.bouncycastle.asn1.x500.X500Name; -import org.bouncycastle.asn1.x509.BasicConstraints; -import org.bouncycastle.asn1.x509.Extension; -import org.bouncycastle.asn1.x509.GeneralName; -import org.bouncycastle.asn1.x509.GeneralNames; -import org.bouncycastle.cert.CertIOException; -import org.bouncycastle.cert.X509v3CertificateBuilder; -import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; -import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.operator.OperatorCreationException; -import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; -import org.bouncycastle.pkcs.PKCS10CertificationRequest; -import org.bouncycastle.util.io.pem.PemObject; -import org.bouncycastle.util.io.pem.PemWriter; -import org.junit.jupiter.api.Test; - -class CertificateToolTest { - private static final String DEFAULT_HOST_NAME = "localhost"; - private static final String DEFAULT_ENCRYPTION = "RSA"; - private static final Provider PROVIDER = new BouncyCastleProvider(); - private static final String BEGIN_CERT = "-----BEGIN CERTIFICATE-----"; - private static final String END_CERT = "-----END CERTIFICATE-----"; - - static { - // adds the Bouncy castle provider to java security - Security.addProvider(PROVIDER); - } - - @Test - void shouldLoadMultipleCertsIntoKeyStore() throws Throwable { - // Given - var certFile = File.createTempFile("3random", ".cer"); - certFile.deleteOnExit(); - - var cert1 = generateSelfSignedCertificate(); - var cert2 = generateSelfSignedCertificate(); - var cert3 = generateSelfSignedCertificate(); - - saveX509Cert(new Certificate[] {cert1, cert2, cert3}, certFile); - - var keyStore = KeyStore.getInstance("JKS"); - keyStore.load(null, null); - - // When - CertificateTool.loadX509Cert(Collections.singletonList(certFile), keyStore); - - // Then - var aliases = keyStore.aliases(); - assertTrue(aliases.hasMoreElements()); - assertTrue(aliases.nextElement().startsWith("neo4j.javadriver.trustedcert")); - assertTrue(aliases.hasMoreElements()); - assertTrue(aliases.nextElement().startsWith("neo4j.javadriver.trustedcert")); - assertTrue(aliases.hasMoreElements()); - assertTrue(aliases.nextElement().startsWith("neo4j.javadriver.trustedcert")); - assertFalse(aliases.hasMoreElements()); - } - - private static KeyPair generateKeyPair() throws NoSuchAlgorithmException { - var keyPairGenerator = KeyPairGenerator.getInstance(DEFAULT_ENCRYPTION); - keyPairGenerator.initialize(2048, new SecureRandom()); - return keyPairGenerator.generateKeyPair(); - } - - private static X509Certificate generateCert( - X500Name issuer, X500Name subject, KeyPair issuerKeys, PublicKey publicKey, GeneralName... generalNames) - throws GeneralSecurityException, OperatorCreationException, CertIOException { - // Create x509 certificate - var startDate = new Date(System.currentTimeMillis()); - var endDate = new Date(System.currentTimeMillis() + 365L * 24L * 60L * 60L * 1000L); - var serialNum = BigInteger.valueOf(System.currentTimeMillis()); - X509v3CertificateBuilder certBuilder = - new JcaX509v3CertificateBuilder(issuer, serialNum, startDate, endDate, subject, publicKey); - - // Subject alternative name (part of SNI extension, used for hostname verification) - Set names = new HashSet<>(); - names.add(new GeneralName(GeneralName.dNSName, DEFAULT_HOST_NAME)); - names.addAll(Arrays.asList(generalNames)); - var subjectAlternativeName = new GeneralNames(names.toArray(new GeneralName[0])); - certBuilder.addExtension(Extension.subjectAlternativeName, false, subjectAlternativeName); - certBuilder.addExtension(Extension.basicConstraints, false, new BasicConstraints(true)); - - // Get the certificate back - var signer = new JcaContentSignerBuilder("SHA512WithRSAEncryption").build(issuerKeys.getPrivate()); - var certHolder = certBuilder.build(signer); - var certificate = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHolder); - - certificate.verify(issuerKeys.getPublic()); - return certificate; - } - - @SuppressWarnings("ResultOfMethodCallIgnored") - private static void writePem(String type, byte[] encodedContent, File path) throws IOException { - if (path.getParentFile() != null && path.getParentFile().exists()) { - path.getParentFile().mkdirs(); - } - try (var writer = new PemWriter(new FileWriter(path))) { - writer.writeObject(new PemObject(type, encodedContent)); - writer.flush(); - } - } - - private static void saveX509Cert(Certificate cert, File certFile) throws GeneralSecurityException, IOException { - saveX509Cert(new Certificate[] {cert}, certFile); - } - - private static void saveX509Cert(Certificate[] certs, File certFile) throws GeneralSecurityException, IOException { - try (var writer = new BufferedWriter(new FileWriter(certFile))) { - for (var cert : certs) { - var certStr = - Base64.getEncoder().encodeToString(cert.getEncoded()).replaceAll("(.{64})", "$1\n"); - - writer.write(BEGIN_CERT); - writer.newLine(); - - writer.write(certStr); - writer.newLine(); - - writer.write(END_CERT); - writer.newLine(); - } - } - } - - private static X509Certificate generateSelfSignedCertificate() - throws GeneralSecurityException, OperatorCreationException, CertIOException { - return new SelfSignedCertificateGenerator().certificate; - } - - private static class SelfSignedCertificateGenerator { - private final KeyPair keyPair; - private final X509Certificate certificate; - - public SelfSignedCertificateGenerator(GeneralName... generalNames) - throws GeneralSecurityException, OperatorCreationException, CertIOException { - // Create the public/private rsa key pair - keyPair = generateKeyPair(); - - // Create x509 certificate - certificate = generateCert( - new X500Name("CN=" + DEFAULT_HOST_NAME), - new X500Name("CN=" + DEFAULT_HOST_NAME), - keyPair, - keyPair.getPublic(), - generalNames); - } - - public void savePrivateKey(File saveTo) throws IOException { - writePem("PRIVATE KEY", keyPair.getPrivate().getEncoded(), saveTo); - } - - public void saveSelfSignedCertificate(File saveTo) throws CertificateEncodingException, IOException { - writePem("CERTIFICATE", certificate.getEncoded(), saveTo); - } - - public X509Certificate sign(PKCS10CertificationRequest csr, PublicKey csrPublicKey, GeneralName... generalNames) - throws GeneralSecurityException, OperatorCreationException, CertIOException { - return generateCert( - X500Name.getInstance( - this.certificate.getSubjectX500Principal().getEncoded()), - csr.getSubject(), - keyPair, - csrPublicKey, - generalNames); - } - } -} diff --git a/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/util/ClusterCompositionUtil.java b/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/util/ClusterCompositionUtil.java deleted file mode 100644 index 336280418f..0000000000 --- a/bolt-api/src/test/java/org/neo4j/driver/internal/bolt/api/util/ClusterCompositionUtil.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.internal.bolt.api.util; - -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.ClusterComposition; - -public final class ClusterCompositionUtil { - private ClusterCompositionUtil() {} - - public static final long NEVER_EXPIRE = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1); - - public static final BoltServerAddress A = new BoltServerAddress("192.168.100.100:11"); - public static final BoltServerAddress B = new BoltServerAddress("192.168.100.101:22"); - public static final BoltServerAddress C = new BoltServerAddress("192.168.100.102:33"); - public static final BoltServerAddress D = new BoltServerAddress("192.168.100.103:44"); - public static final BoltServerAddress E = new BoltServerAddress("192.168.100.104:55"); - public static final BoltServerAddress F = new BoltServerAddress("192.168.100.105:66"); - - public static final List EMPTY = new ArrayList<>(); - - @SafeVarargs - public static ClusterComposition createClusterComposition(List... servers) { - return createClusterComposition(NEVER_EXPIRE, servers); - } - - @SafeVarargs - @SuppressWarnings("fallthrough") - public static ClusterComposition createClusterComposition( - long expirationTimestamp, List... servers) { - Set routers = new LinkedHashSet<>(); - Set writers = new LinkedHashSet<>(); - Set readers = new LinkedHashSet<>(); - - switch (servers.length) { - case 3: - readers.addAll(servers[2]); - // no break on purpose - case 2: - writers.addAll(servers[1]); - // no break on purpose - case 1: - routers.addAll(servers[0]); - } - return new ClusterComposition(expirationTimestamp, readers, writers, routers, null); - } -} diff --git a/bundle/LICENSES.txt b/bundle/LICENSES.txt index 66326c3beb..64fa274009 100644 --- a/bundle/LICENSES.txt +++ b/bundle/LICENSES.txt @@ -4,6 +4,10 @@ libraries. For an overview of the licenses see the NOTICE.txt file. ------------------------------------------------------------------------------ Apache Software License, Version 2.0 + Neo4j Bolt Connection (Netty reference impl) + Neo4j Bolt Connection (Pooled provider impl) + Neo4j Bolt Connection (Provider SPI) + Neo4j Bolt Connection (Routed provider impl) Netty/Buffer Netty/Codec Netty/Common diff --git a/bundle/NOTICE.txt b/bundle/NOTICE.txt index 1fd7e9ad1c..988e9585e5 100644 --- a/bundle/NOTICE.txt +++ b/bundle/NOTICE.txt @@ -19,6 +19,10 @@ Third-party licenses -------------------- Apache Software License, Version 2.0 + Neo4j Bolt Connection (Netty reference impl) + Neo4j Bolt Connection (Pooled provider impl) + Neo4j Bolt Connection (Provider SPI) + Neo4j Bolt Connection (Routed provider impl) Netty/Buffer Netty/Codec Netty/Common diff --git a/bundle/pom.xml b/bundle/pom.xml index b4797c254f..ae2cc179a0 100644 --- a/bundle/pom.xml +++ b/bundle/pom.xml @@ -32,45 +32,6 @@ ${project.version} true - - org.neo4j.driver - neo4j-bolt-api - ${project.version} - true - - - org.neo4j.driver - neo4j-bolt-api-netty - ${project.version} - true - - - org.neo4j.driver - neo4j-bolt-api-pooled - ${project.version} - true - - - org.neo4j.driver - neo4j-bolt-api-routed - ${project.version} - true - - - io.netty - netty-handler - true - - - io.netty - netty-tcnative-classes - true - - - io.projectreactor - reactor-core - true - @@ -121,7 +82,7 @@ <_removeheaders>Bnd-*,Private-Package,Bundle-ClassPath,Embed-Dependency,Embed-Transitive,Embedded-Artifacts,Include-Resource - neo4j-bolt-api-netty,netty-handler,netty-tcnative-classes,reactor-core + neo4j-bolt-connection-netty,netty-handler,netty-tcnative-classes,reactor-core @@ -232,38 +193,18 @@ - ${project.groupId}:neo4j-bolt-api - ${project.groupId}:neo4j-bolt-api-netty - ${project.groupId}:neo4j-bolt-api-pooled - ${project.groupId}:neo4j-bolt-api-routed + org.neo4j.bolt:neo4j-bolt-connection + org.neo4j.bolt:neo4j-bolt-connection-netty + org.neo4j.bolt:neo4j-bolt-connection-pooled + org.neo4j.bolt:neo4j-bolt-connection-routed io.netty:* io.projectreactor:* - org.neo4j.driver.internal.bolt.api - org.neo4j.driver.internal.bolt.api - - - org.neo4j.driver.internal.bolt.basicimpl.impl - org.neo4j.driver.internal.bolt.basicimpl - - - org.neo4j.driver.internal.bolt.basicimpl.BootstrapFactory - org.neo4j.driver.internal.bolt.basicimpl.BootstrapFactory - - - org.neo4j.driver.internal.bolt.basicimpl.NettyBoltConnectionProvider - org.neo4j.driver.internal.bolt.basicimpl.NettyBoltConnectionProvider - - - org.neo4j.driver.internal.bolt.pooledimpl - org.neo4j.driver.internal.bolt.pooledimpl - - - org.neo4j.driver.internal.bolt.routedimpl - org.neo4j.driver.internal.bolt.routedimpl + org.neo4j.bolt.connection + org.neo4j.driver.internal.shaded.bolt.connection io.netty diff --git a/bundle/src/main/jpms/module-info.java b/bundle/src/main/jpms/module-info.java index fe4ecdc99f..a6ddc48221 100644 --- a/bundle/src/main/jpms/module-info.java +++ b/bundle/src/main/jpms/module-info.java @@ -28,11 +28,12 @@ exports org.neo4j.driver.net; exports org.neo4j.driver.util; exports org.neo4j.driver.exceptions; + exports org.neo4j.driver.exceptions.value; requires transitive java.logging; requires transitive org.reactivestreams; requires static micrometer.core; - requires static org.graalvm.sdk; + requires static org.graalvm.nativeimage; requires static org.slf4j; requires static java.management; requires static reactor.blockhound; diff --git a/driver/LICENSES.txt b/driver/LICENSES.txt index 66326c3beb..64fa274009 100644 --- a/driver/LICENSES.txt +++ b/driver/LICENSES.txt @@ -4,6 +4,10 @@ libraries. For an overview of the licenses see the NOTICE.txt file. ------------------------------------------------------------------------------ Apache Software License, Version 2.0 + Neo4j Bolt Connection (Netty reference impl) + Neo4j Bolt Connection (Pooled provider impl) + Neo4j Bolt Connection (Provider SPI) + Neo4j Bolt Connection (Routed provider impl) Netty/Buffer Netty/Codec Netty/Common diff --git a/driver/NOTICE.txt b/driver/NOTICE.txt index 1fd7e9ad1c..988e9585e5 100644 --- a/driver/NOTICE.txt +++ b/driver/NOTICE.txt @@ -19,6 +19,10 @@ Third-party licenses -------------------- Apache Software License, Version 2.0 + Neo4j Bolt Connection (Netty reference impl) + Neo4j Bolt Connection (Pooled provider impl) + Neo4j Bolt Connection (Provider SPI) + Neo4j Bolt Connection (Routed provider impl) Netty/Buffer Netty/Codec Netty/Common diff --git a/driver/pom.xml b/driver/pom.xml index c7047a5ad5..5a04e50398 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -20,8 +20,7 @@ ${project.basedir}/.. ${basedir}/target/classes-without-jpms ,-try - --add-opens - org.neo4j.driver/org.neo4j.driver.internal.bolt.basicimpl.impl.util.messaging=ALL-UNNAMED + --add-opens org.neo4j.driver/org.neo4j.bolt.connection.netty.impl.util.messaging=ALL-UNNAMED --add-opens org.neo4j.driver/org.neo4j.driver.internal.util=ALL-UNNAMED --add-opens org.neo4j.driver/org.neo4j.driver.internal.async=ALL-UNNAMED blockHoundTest false @@ -30,41 +29,25 @@ - org.neo4j.driver - neo4j-bolt-api - ${project.version} - true + org.neo4j.bolt + neo4j-bolt-connection - org.neo4j.driver - neo4j-bolt-api-netty - ${project.version} - true + org.neo4j.bolt + neo4j-bolt-connection-netty - org.neo4j.driver - neo4j-bolt-api-pooled - ${project.version} - true + org.neo4j.bolt + neo4j-bolt-connection-pooled - org.neo4j.driver - neo4j-bolt-api-routed - ${project.version} - true + org.neo4j.bolt + neo4j-bolt-connection-routed org.reactivestreams reactive-streams - - io.netty - netty-handler - - - io.netty - netty-tcnative-classes - io.projectreactor reactor-core @@ -143,10 +126,6 @@ ch.qos.logback logback-classic - - com.tngtech.archunit - archunit-junit5 - @@ -221,124 +200,6 @@ - - org.apache.maven.plugins - maven-shade-plugin - - - package - - shade - - - - - ${project.groupId}:neo4j-bolt-api - ${project.groupId}:neo4j-bolt-api-netty - ${project.groupId}:neo4j-bolt-api-pooled - ${project.groupId}:neo4j-bolt-api-routed - - - - - org.neo4j.driver.internal.bolt.api - org.neo4j.driver.internal.bolt.api - - - org.neo4j.driver.internal.bolt.basicimpl.impl - org.neo4j.driver.internal.bolt.basicimpl - - - org.neo4j.driver.internal.bolt.basicimpl.BootstrapFactory - org.neo4j.driver.internal.bolt.basicimpl.BootstrapFactory - - - org.neo4j.driver.internal.bolt.basicimpl.NettyBoltConnectionProvider - org.neo4j.driver.internal.bolt.basicimpl.NettyBoltConnectionProvider - - - org.neo4j.driver.internal.bolt.pooledimpl - org.neo4j.driver.internal.bolt.pooledimpl - - - org.neo4j.driver.internal.bolt.routedimpl - org.neo4j.driver.internal.bolt.routedimpl - - - - - - - META-INF/services/reactor.blockhound.integration.BlockHoundIntegration=src/main/resources/META-INF/services/reactor.blockhound.integration.BlockHoundIntegration,META-INF/native-image/org.neo4j.driver/neo4j-java-driver/native-image.properties=src/main/resources/META-INF/native-image/org.neo4j.driver/neo4j-java-driver/native-image.properties,META-INF/native-image/org.neo4j.driver/neo4j-java-driver/reflect-config.json=src/main/resources/META-INF/native-image/org.neo4j.driver/neo4j-java-driver/reflect-config.json - - - - - - *:* - - module-info.java - META-INF/maven/** - - - - true - true - - - - - - org.apache.maven.plugins - maven-antrun-plugin - - - add-module-info-to-sources - package - - run - - - - - - - - - - - - - org.moditect - moditect-maven-plugin - - - add-module-infos - package - - add-module-info - - - true - - - ${basedir}/src/main/jpms/module-info.java - - - - - - - - org.apache.felix - maven-bundle-plugin - - - <_removeheaders>Bnd-*,Private-Package,Bundle-ClassPath,Embed-Dependency,Embed-Transitive,Embedded-Artifacts,Include-Resource - neo4j-bolt-api-netty - - - @@ -412,18 +273,6 @@ - - org.apache.maven.plugins - maven-shade-plugin - - - org.apache.maven.plugins - maven-antrun-plugin - - - org.moditect - moditect-maven-plugin - diff --git a/driver/src/main/java/module-info.java b/driver/src/main/java/module-info.java index edcb38d56c..a3038b569c 100644 --- a/driver/src/main/java/module-info.java +++ b/driver/src/main/java/module-info.java @@ -30,10 +30,10 @@ exports org.neo4j.driver.exceptions; exports org.neo4j.driver.exceptions.value; - requires org.neo4j.bolt.api; - requires org.neo4j.bolt.netty; - requires org.neo4j.bolt.pooled; - requires org.neo4j.bolt.routed; + requires org.neo4j.bolt.connection; + requires org.neo4j.bolt.connection.netty; + requires org.neo4j.bolt.connection.pooled; + requires org.neo4j.bolt.connection.routed; requires reactor.core; requires io.netty.common; requires transitive java.logging; diff --git a/driver/src/main/java/org/neo4j/driver/internal/BoltLoggingProvider.java b/driver/src/main/java/org/neo4j/driver/internal/BoltLoggingProvider.java index 1448239e4e..d3a638ddfe 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/BoltLoggingProvider.java +++ b/driver/src/main/java/org/neo4j/driver/internal/BoltLoggingProvider.java @@ -16,8 +16,8 @@ */ package org.neo4j.driver.internal; +import org.neo4j.bolt.connection.LoggingProvider; import org.neo4j.driver.Logging; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; public class BoltLoggingProvider implements LoggingProvider { private final Logging logging; diff --git a/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java b/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java index a5fa0abef9..10e65a3d5a 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java +++ b/driver/src/main/java/org/neo4j/driver/internal/DriverFactory.java @@ -33,6 +33,19 @@ import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; +import org.neo4j.bolt.connection.BoltAgent; +import org.neo4j.bolt.connection.BoltConnectionProvider; +import org.neo4j.bolt.connection.BoltServerAddress; +import org.neo4j.bolt.connection.DefaultDomainNameResolver; +import org.neo4j.bolt.connection.DomainNameResolver; +import org.neo4j.bolt.connection.LoggingProvider; +import org.neo4j.bolt.connection.MetricsListener; +import org.neo4j.bolt.connection.RoutingContext; +import org.neo4j.bolt.connection.netty.BootstrapFactory; +import org.neo4j.bolt.connection.netty.NettyBoltConnectionProvider; +import org.neo4j.bolt.connection.pooled.PooledBoltConnectionProvider; +import org.neo4j.bolt.connection.routed.Rediscovery; +import org.neo4j.bolt.connection.routed.RoutedBoltConnectionProvider; import org.neo4j.driver.AuthTokenManager; import org.neo4j.driver.ClientCertificateManager; import org.neo4j.driver.Config; @@ -42,19 +55,6 @@ import org.neo4j.driver.internal.adaptedbolt.AdaptingDriverBoltConnectionProvider; import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnectionProvider; import org.neo4j.driver.internal.adaptedbolt.ErrorMapper; -import org.neo4j.driver.internal.bolt.api.BoltAgent; -import org.neo4j.driver.internal.bolt.api.BoltConnectionProvider; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.DefaultDomainNameResolver; -import org.neo4j.driver.internal.bolt.api.DomainNameResolver; -import org.neo4j.driver.internal.bolt.api.LoggingProvider; -import org.neo4j.driver.internal.bolt.api.MetricsListener; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.basicimpl.BootstrapFactory; -import org.neo4j.driver.internal.bolt.basicimpl.NettyBoltConnectionProvider; -import org.neo4j.driver.internal.bolt.pooledimpl.PooledBoltConnectionProvider; -import org.neo4j.driver.internal.bolt.routedimpl.Rediscovery; -import org.neo4j.driver.internal.bolt.routedimpl.RoutedBoltConnectionProvider; import org.neo4j.driver.internal.boltlistener.BoltConnectionListener; import org.neo4j.driver.internal.homedb.HomeDatabaseCache; import org.neo4j.driver.internal.metrics.DevNullMetricsProvider; diff --git a/driver/src/main/java/org/neo4j/driver/internal/InternalExecutableQuery.java b/driver/src/main/java/org/neo4j/driver/internal/InternalExecutableQuery.java index 9e785851ed..cb01762fe1 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/InternalExecutableQuery.java +++ b/driver/src/main/java/org/neo4j/driver/internal/InternalExecutableQuery.java @@ -20,6 +20,7 @@ import java.util.Map; import java.util.stream.Collector; +import org.neo4j.bolt.connection.TelemetryApi; import org.neo4j.driver.AccessMode; import org.neo4j.driver.AuthToken; import org.neo4j.driver.Driver; @@ -32,7 +33,6 @@ import org.neo4j.driver.SessionConfig; import org.neo4j.driver.TransactionCallback; import org.neo4j.driver.TransactionConfig; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; public class InternalExecutableQuery implements ExecutableQuery { private final Driver driver; diff --git a/driver/src/main/java/org/neo4j/driver/internal/InternalIsoDuration.java b/driver/src/main/java/org/neo4j/driver/internal/InternalIsoDuration.java index 7cc9b5e587..7dba4b5e74 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/InternalIsoDuration.java +++ b/driver/src/main/java/org/neo4j/driver/internal/InternalIsoDuration.java @@ -30,7 +30,7 @@ import java.util.Objects; import org.neo4j.driver.types.IsoDuration; -public class InternalIsoDuration implements IsoDuration, org.neo4j.driver.internal.bolt.api.values.IsoDuration { +public class InternalIsoDuration implements IsoDuration, org.neo4j.bolt.connection.values.IsoDuration { private static final long NANOS_PER_SECOND = 1_000_000_000; private static final List SUPPORTED_UNITS = List.of(MONTHS, DAYS, SECONDS, NANOS); diff --git a/driver/src/main/java/org/neo4j/driver/internal/InternalNode.java b/driver/src/main/java/org/neo4j/driver/internal/InternalNode.java index b39b8da698..6fd5e63356 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/InternalNode.java +++ b/driver/src/main/java/org/neo4j/driver/internal/InternalNode.java @@ -26,7 +26,7 @@ /** * {@link Node} implementation that directly contains labels and properties. */ -public class InternalNode extends InternalEntity implements Node, org.neo4j.driver.internal.bolt.api.values.Node { +public class InternalNode extends InternalEntity implements Node, org.neo4j.bolt.connection.values.Node { private final Collection labels; public InternalNode(long id) { diff --git a/driver/src/main/java/org/neo4j/driver/internal/InternalPath.java b/driver/src/main/java/org/neo4j/driver/internal/InternalPath.java index b34d32a549..802d365d37 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/InternalPath.java +++ b/driver/src/main/java/org/neo4j/driver/internal/InternalPath.java @@ -31,9 +31,9 @@ /** * {@link Path} implementation that directly contains all nodes and relationships. */ -public class InternalPath implements Path, AsValue, org.neo4j.driver.internal.bolt.api.values.Path { +public class InternalPath implements Path, AsValue, org.neo4j.bolt.connection.values.Path { public record SelfContainedSegment(Node start, Relationship relationship, Node end) - implements Segment, org.neo4j.driver.internal.bolt.api.values.Segment { + implements Segment, org.neo4j.bolt.connection.values.Segment { @Override public boolean equals(Object other) { diff --git a/driver/src/main/java/org/neo4j/driver/internal/InternalPoint2D.java b/driver/src/main/java/org/neo4j/driver/internal/InternalPoint2D.java index 7e2980eb44..a065f0158d 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/InternalPoint2D.java +++ b/driver/src/main/java/org/neo4j/driver/internal/InternalPoint2D.java @@ -18,8 +18,7 @@ import org.neo4j.driver.types.Point; -public record InternalPoint2D(int srid, double x, double y) - implements Point, org.neo4j.driver.internal.bolt.api.values.Point { +public record InternalPoint2D(int srid, double x, double y) implements Point, org.neo4j.bolt.connection.values.Point { @Override public double z() { diff --git a/driver/src/main/java/org/neo4j/driver/internal/InternalPoint3D.java b/driver/src/main/java/org/neo4j/driver/internal/InternalPoint3D.java index 7b83421c90..ae9c1a977d 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/InternalPoint3D.java +++ b/driver/src/main/java/org/neo4j/driver/internal/InternalPoint3D.java @@ -19,7 +19,7 @@ import org.neo4j.driver.types.Point; public record InternalPoint3D(int srid, double x, double y, double z) - implements Point, org.neo4j.driver.internal.bolt.api.values.Point { + implements Point, org.neo4j.bolt.connection.values.Point { @Override public boolean equals(Object o) { diff --git a/driver/src/main/java/org/neo4j/driver/internal/InternalRelationship.java b/driver/src/main/java/org/neo4j/driver/internal/InternalRelationship.java index 7d37805601..9cf73ab94c 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/InternalRelationship.java +++ b/driver/src/main/java/org/neo4j/driver/internal/InternalRelationship.java @@ -26,7 +26,7 @@ * {@link Relationship} implementation that directly contains type and properties. */ public class InternalRelationship extends InternalEntity - implements Relationship, org.neo4j.driver.internal.bolt.api.values.Relationship { + implements Relationship, org.neo4j.bolt.connection.values.Relationship { private long start; private String startElementId; private long end; diff --git a/driver/src/main/java/org/neo4j/driver/internal/InternalSession.java b/driver/src/main/java/org/neo4j/driver/internal/InternalSession.java index c8ff81888c..0a3d3cf172 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/InternalSession.java +++ b/driver/src/main/java/org/neo4j/driver/internal/InternalSession.java @@ -20,6 +20,7 @@ import java.util.Map; import java.util.Set; +import org.neo4j.bolt.connection.TelemetryApi; import org.neo4j.driver.AccessMode; import org.neo4j.driver.Bookmark; import org.neo4j.driver.Query; @@ -32,7 +33,6 @@ import org.neo4j.driver.exceptions.ClientException; import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnection; import org.neo4j.driver.internal.async.NetworkSession; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; import org.neo4j.driver.internal.telemetry.ApiTelemetryWork; import org.neo4j.driver.internal.util.Futures; diff --git a/driver/src/main/java/org/neo4j/driver/internal/NotificationConfigMapper.java b/driver/src/main/java/org/neo4j/driver/internal/NotificationConfigMapper.java index c63be23ce3..33a3ed9a5b 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/NotificationConfigMapper.java +++ b/driver/src/main/java/org/neo4j/driver/internal/NotificationConfigMapper.java @@ -17,10 +17,10 @@ package org.neo4j.driver.internal; import java.util.stream.Collectors; +import org.neo4j.bolt.connection.NotificationClassification; +import org.neo4j.bolt.connection.NotificationConfig; +import org.neo4j.bolt.connection.NotificationSeverity; import org.neo4j.driver.NotificationCategory; -import org.neo4j.driver.internal.bolt.api.NotificationClassification; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.NotificationSeverity; public class NotificationConfigMapper { public static NotificationConfig map(org.neo4j.driver.NotificationConfig config) { diff --git a/driver/src/main/java/org/neo4j/driver/internal/RoutingSettings.java b/driver/src/main/java/org/neo4j/driver/internal/RoutingSettings.java index c29826f34d..76619bf25d 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/RoutingSettings.java +++ b/driver/src/main/java/org/neo4j/driver/internal/RoutingSettings.java @@ -18,7 +18,7 @@ import static java.util.concurrent.TimeUnit.SECONDS; -import org.neo4j.driver.internal.bolt.api.RoutingContext; +import org.neo4j.bolt.connection.RoutingContext; public record RoutingSettings(long routingTablePurgeDelayMs, RoutingContext routingContext) { public static final long STALE_ROUTING_TABLE_PURGE_DELAY_MS = SECONDS.toMillis(30); diff --git a/driver/src/main/java/org/neo4j/driver/internal/SessionFactoryImpl.java b/driver/src/main/java/org/neo4j/driver/internal/SessionFactoryImpl.java index 7f2103da2d..b8e8a31065 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/SessionFactoryImpl.java +++ b/driver/src/main/java/org/neo4j/driver/internal/SessionFactoryImpl.java @@ -23,6 +23,9 @@ import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletionStage; +import org.neo4j.bolt.connection.DatabaseName; +import org.neo4j.bolt.connection.DatabaseNameUtil; +import org.neo4j.bolt.connection.SecurityPlan; import org.neo4j.driver.AccessMode; import org.neo4j.driver.AuthToken; import org.neo4j.driver.AuthTokenManager; @@ -36,9 +39,6 @@ import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnectionProvider; import org.neo4j.driver.internal.async.LeakLoggingNetworkSession; import org.neo4j.driver.internal.async.NetworkSession; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.DatabaseNameUtil; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; import org.neo4j.driver.internal.homedb.HomeDatabaseCache; import org.neo4j.driver.internal.retry.RetryLogic; import org.neo4j.driver.internal.security.BoltSecurityPlanManager; diff --git a/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/AdaptingDriverBoltConnection.java b/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/AdaptingDriverBoltConnection.java index f7ad0fe856..94e7dc119a 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/AdaptingDriverBoltConnection.java +++ b/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/AdaptingDriverBoltConnection.java @@ -21,18 +21,18 @@ import java.util.Objects; import java.util.Set; import java.util.concurrent.CompletionStage; +import org.neo4j.bolt.connection.AccessMode; +import org.neo4j.bolt.connection.AuthInfo; +import org.neo4j.bolt.connection.AuthTokens; +import org.neo4j.bolt.connection.BoltConnection; +import org.neo4j.bolt.connection.BoltConnectionState; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.BoltServerAddress; +import org.neo4j.bolt.connection.DatabaseName; +import org.neo4j.bolt.connection.NotificationConfig; +import org.neo4j.bolt.connection.TelemetryApi; +import org.neo4j.bolt.connection.TransactionType; import org.neo4j.driver.Value; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.AuthInfo; -import org.neo4j.driver.internal.bolt.api.AuthTokens; -import org.neo4j.driver.internal.bolt.api.BoltConnection; -import org.neo4j.driver.internal.bolt.api.BoltConnectionState; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; -import org.neo4j.driver.internal.bolt.api.TransactionType; import org.neo4j.driver.internal.value.BoltValueFactory; final class AdaptingDriverBoltConnection implements DriverBoltConnection { diff --git a/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/AdaptingDriverBoltConnectionProvider.java b/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/AdaptingDriverBoltConnectionProvider.java index f4761664ab..33bb87e0be 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/AdaptingDriverBoltConnectionProvider.java +++ b/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/AdaptingDriverBoltConnectionProvider.java @@ -22,17 +22,17 @@ import java.util.concurrent.CompletionStage; import java.util.function.Consumer; import java.util.function.Supplier; +import org.neo4j.bolt.connection.AccessMode; +import org.neo4j.bolt.connection.AuthTokens; +import org.neo4j.bolt.connection.BoltAgent; +import org.neo4j.bolt.connection.BoltConnectionProvider; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.BoltServerAddress; +import org.neo4j.bolt.connection.DatabaseName; +import org.neo4j.bolt.connection.NotificationConfig; +import org.neo4j.bolt.connection.RoutingContext; +import org.neo4j.bolt.connection.SecurityPlan; import org.neo4j.driver.Value; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.AuthTokens; -import org.neo4j.driver.internal.bolt.api.BoltAgent; -import org.neo4j.driver.internal.bolt.api.BoltConnectionProvider; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; import org.neo4j.driver.internal.value.BoltValueFactory; public class AdaptingDriverBoltConnectionProvider implements DriverBoltConnectionProvider { diff --git a/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/AdaptingDriverResponseHandler.java b/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/AdaptingDriverResponseHandler.java index a47aaa0512..a503069597 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/AdaptingDriverResponseHandler.java +++ b/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/AdaptingDriverResponseHandler.java @@ -19,19 +19,19 @@ import java.util.Arrays; import java.util.Map; import java.util.Objects; +import org.neo4j.bolt.connection.ResponseHandler; +import org.neo4j.bolt.connection.summary.BeginSummary; +import org.neo4j.bolt.connection.summary.CommitSummary; +import org.neo4j.bolt.connection.summary.DiscardSummary; +import org.neo4j.bolt.connection.summary.LogoffSummary; +import org.neo4j.bolt.connection.summary.LogonSummary; +import org.neo4j.bolt.connection.summary.PullSummary; +import org.neo4j.bolt.connection.summary.ResetSummary; +import org.neo4j.bolt.connection.summary.RollbackSummary; +import org.neo4j.bolt.connection.summary.RouteSummary; +import org.neo4j.bolt.connection.summary.RunSummary; +import org.neo4j.bolt.connection.summary.TelemetrySummary; import org.neo4j.driver.Value; -import org.neo4j.driver.internal.bolt.api.ResponseHandler; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.CommitSummary; -import org.neo4j.driver.internal.bolt.api.summary.DiscardSummary; -import org.neo4j.driver.internal.bolt.api.summary.LogoffSummary; -import org.neo4j.driver.internal.bolt.api.summary.LogonSummary; -import org.neo4j.driver.internal.bolt.api.summary.PullSummary; -import org.neo4j.driver.internal.bolt.api.summary.ResetSummary; -import org.neo4j.driver.internal.bolt.api.summary.RollbackSummary; -import org.neo4j.driver.internal.bolt.api.summary.RouteSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.summary.TelemetrySummary; import org.neo4j.driver.internal.value.BoltValue; import org.neo4j.driver.internal.value.BoltValueFactory; @@ -63,7 +63,7 @@ public void onRunSummary(RunSummary summary) { } @Override - public void onRecord(org.neo4j.driver.internal.bolt.api.values.Value[] fields) { + public void onRecord(org.neo4j.bolt.connection.values.Value[] fields) { var mappedFields = Arrays.stream(fields) .map(field -> ((BoltValue) field).asDriverValue()) .toArray(Value[]::new); diff --git a/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/BasicResponseHandler.java b/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/BasicResponseHandler.java index 0c4a16506f..3736ca539b 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/BasicResponseHandler.java +++ b/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/BasicResponseHandler.java @@ -21,19 +21,19 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.concurrent.CompletionStage; +import org.neo4j.bolt.connection.summary.BeginSummary; +import org.neo4j.bolt.connection.summary.CommitSummary; +import org.neo4j.bolt.connection.summary.LogoffSummary; +import org.neo4j.bolt.connection.summary.LogonSummary; +import org.neo4j.bolt.connection.summary.ResetSummary; +import org.neo4j.bolt.connection.summary.RollbackSummary; +import org.neo4j.bolt.connection.summary.RouteSummary; +import org.neo4j.bolt.connection.summary.RunSummary; +import org.neo4j.bolt.connection.summary.TelemetrySummary; import org.neo4j.driver.Value; import org.neo4j.driver.exceptions.Neo4jException; import org.neo4j.driver.internal.adaptedbolt.summary.DiscardSummary; import org.neo4j.driver.internal.adaptedbolt.summary.PullSummary; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.CommitSummary; -import org.neo4j.driver.internal.bolt.api.summary.LogoffSummary; -import org.neo4j.driver.internal.bolt.api.summary.LogonSummary; -import org.neo4j.driver.internal.bolt.api.summary.ResetSummary; -import org.neo4j.driver.internal.bolt.api.summary.RollbackSummary; -import org.neo4j.driver.internal.bolt.api.summary.RouteSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.summary.TelemetrySummary; public class BasicResponseHandler implements DriverResponseHandler { private final CompletableFuture summariesFuture = new CompletableFuture<>(); diff --git a/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/DriverBoltConnection.java b/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/DriverBoltConnection.java index ea9cce92e8..ea4b383eb9 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/DriverBoltConnection.java +++ b/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/DriverBoltConnection.java @@ -20,16 +20,16 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.CompletionStage; +import org.neo4j.bolt.connection.AccessMode; +import org.neo4j.bolt.connection.AuthInfo; +import org.neo4j.bolt.connection.BoltConnectionState; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.BoltServerAddress; +import org.neo4j.bolt.connection.DatabaseName; +import org.neo4j.bolt.connection.NotificationConfig; +import org.neo4j.bolt.connection.TelemetryApi; +import org.neo4j.bolt.connection.TransactionType; import org.neo4j.driver.Value; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.AuthInfo; -import org.neo4j.driver.internal.bolt.api.BoltConnectionState; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; -import org.neo4j.driver.internal.bolt.api.TransactionType; public interface DriverBoltConnection { CompletionStage onLoop(); diff --git a/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/DriverBoltConnectionProvider.java b/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/DriverBoltConnectionProvider.java index 5ec72c81d5..ad6667a747 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/DriverBoltConnectionProvider.java +++ b/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/DriverBoltConnectionProvider.java @@ -21,12 +21,12 @@ import java.util.concurrent.CompletionStage; import java.util.function.Consumer; import java.util.function.Supplier; +import org.neo4j.bolt.connection.AccessMode; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.DatabaseName; +import org.neo4j.bolt.connection.NotificationConfig; +import org.neo4j.bolt.connection.SecurityPlan; import org.neo4j.driver.Value; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; public interface DriverBoltConnectionProvider { diff --git a/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/DriverResponseHandler.java b/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/DriverResponseHandler.java index a6224f1d77..b575b62d74 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/DriverResponseHandler.java +++ b/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/DriverResponseHandler.java @@ -16,18 +16,18 @@ */ package org.neo4j.driver.internal.adaptedbolt; +import org.neo4j.bolt.connection.summary.BeginSummary; +import org.neo4j.bolt.connection.summary.CommitSummary; +import org.neo4j.bolt.connection.summary.LogoffSummary; +import org.neo4j.bolt.connection.summary.LogonSummary; +import org.neo4j.bolt.connection.summary.ResetSummary; +import org.neo4j.bolt.connection.summary.RollbackSummary; +import org.neo4j.bolt.connection.summary.RouteSummary; +import org.neo4j.bolt.connection.summary.RunSummary; +import org.neo4j.bolt.connection.summary.TelemetrySummary; import org.neo4j.driver.Value; import org.neo4j.driver.internal.adaptedbolt.summary.DiscardSummary; import org.neo4j.driver.internal.adaptedbolt.summary.PullSummary; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.CommitSummary; -import org.neo4j.driver.internal.bolt.api.summary.LogoffSummary; -import org.neo4j.driver.internal.bolt.api.summary.LogonSummary; -import org.neo4j.driver.internal.bolt.api.summary.ResetSummary; -import org.neo4j.driver.internal.bolt.api.summary.RollbackSummary; -import org.neo4j.driver.internal.bolt.api.summary.RouteSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.summary.TelemetrySummary; public interface DriverResponseHandler { diff --git a/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/ErrorMapper.java b/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/ErrorMapper.java index 44c8c0f23f..ca321018d7 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/ErrorMapper.java +++ b/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/ErrorMapper.java @@ -19,6 +19,17 @@ import java.util.Map; import java.util.concurrent.CompletionException; import javax.net.ssl.SSLHandshakeException; +import org.neo4j.bolt.connection.exception.BoltClientException; +import org.neo4j.bolt.connection.exception.BoltConnectionAcquisitionException; +import org.neo4j.bolt.connection.exception.BoltConnectionReadTimeoutException; +import org.neo4j.bolt.connection.exception.BoltDiscoveryException; +import org.neo4j.bolt.connection.exception.BoltFailureException; +import org.neo4j.bolt.connection.exception.BoltGqlErrorException; +import org.neo4j.bolt.connection.exception.BoltProtocolException; +import org.neo4j.bolt.connection.exception.BoltServiceUnavailableException; +import org.neo4j.bolt.connection.exception.BoltTransientException; +import org.neo4j.bolt.connection.exception.BoltUnsupportedFeatureException; +import org.neo4j.bolt.connection.exception.BoltUntrustedServerException; import org.neo4j.driver.Value; import org.neo4j.driver.exceptions.AuthenticationException; import org.neo4j.driver.exceptions.AuthorizationExpiredException; @@ -38,17 +49,6 @@ import org.neo4j.driver.exceptions.UnsupportedFeatureException; import org.neo4j.driver.exceptions.UntrustedServerException; import org.neo4j.driver.internal.GqlStatusError; -import org.neo4j.driver.internal.bolt.api.exception.BoltClientException; -import org.neo4j.driver.internal.bolt.api.exception.BoltConnectionAcquisitionException; -import org.neo4j.driver.internal.bolt.api.exception.BoltConnectionReadTimeoutException; -import org.neo4j.driver.internal.bolt.api.exception.BoltDiscoveryException; -import org.neo4j.driver.internal.bolt.api.exception.BoltFailureException; -import org.neo4j.driver.internal.bolt.api.exception.BoltGqlErrorException; -import org.neo4j.driver.internal.bolt.api.exception.BoltProtocolException; -import org.neo4j.driver.internal.bolt.api.exception.BoltServiceUnavailableException; -import org.neo4j.driver.internal.bolt.api.exception.BoltTransientException; -import org.neo4j.driver.internal.bolt.api.exception.BoltUnsupportedFeatureException; -import org.neo4j.driver.internal.bolt.api.exception.BoltUntrustedServerException; import org.neo4j.driver.internal.util.Futures; import org.neo4j.driver.internal.value.BoltValueFactory; diff --git a/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/RoutedErrorMapper.java b/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/RoutedErrorMapper.java index 971037d7d6..00eb99e7b2 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/RoutedErrorMapper.java +++ b/driver/src/main/java/org/neo4j/driver/internal/adaptedbolt/RoutedErrorMapper.java @@ -19,13 +19,13 @@ import static java.lang.String.format; import java.util.Objects; +import org.neo4j.bolt.connection.AccessMode; +import org.neo4j.bolt.connection.BoltServerAddress; +import org.neo4j.bolt.connection.exception.BoltFailureException; +import org.neo4j.bolt.connection.exception.BoltServiceUnavailableException; import org.neo4j.driver.exceptions.ClientException; import org.neo4j.driver.exceptions.SessionExpiredException; import org.neo4j.driver.internal.GqlStatusError; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.exception.BoltFailureException; -import org.neo4j.driver.internal.bolt.api.exception.BoltServiceUnavailableException; class RoutedErrorMapper extends ErrorMapper { private final BoltServerAddress address; diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/ConnectionContext.java b/driver/src/main/java/org/neo4j/driver/internal/async/ConnectionContext.java index 70aa68bb74..69abec7038 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/ConnectionContext.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/ConnectionContext.java @@ -18,9 +18,9 @@ import java.util.Set; import java.util.concurrent.CompletableFuture; +import org.neo4j.bolt.connection.DatabaseName; import org.neo4j.driver.AuthToken; import org.neo4j.driver.Bookmark; -import org.neo4j.driver.internal.bolt.api.DatabaseName; public interface ConnectionContext { diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/DelegatingBoltConnection.java b/driver/src/main/java/org/neo4j/driver/internal/async/DelegatingBoltConnection.java index 1d596bf862..faef188860 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/DelegatingBoltConnection.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/DelegatingBoltConnection.java @@ -21,18 +21,18 @@ import java.util.Objects; import java.util.Set; import java.util.concurrent.CompletionStage; +import org.neo4j.bolt.connection.AccessMode; +import org.neo4j.bolt.connection.AuthInfo; +import org.neo4j.bolt.connection.BoltConnectionState; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.BoltServerAddress; +import org.neo4j.bolt.connection.DatabaseName; +import org.neo4j.bolt.connection.NotificationConfig; +import org.neo4j.bolt.connection.TelemetryApi; +import org.neo4j.bolt.connection.TransactionType; import org.neo4j.driver.Value; import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnection; import org.neo4j.driver.internal.adaptedbolt.DriverResponseHandler; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.AuthInfo; -import org.neo4j.driver.internal.bolt.api.BoltConnectionState; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; -import org.neo4j.driver.internal.bolt.api.TransactionType; public abstract class DelegatingBoltConnection implements DriverBoltConnection { protected final DriverBoltConnection delegate; diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/DelegatingResponseHandler.java b/driver/src/main/java/org/neo4j/driver/internal/async/DelegatingResponseHandler.java index 32e63ba17d..15ea6ee4e0 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/DelegatingResponseHandler.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/DelegatingResponseHandler.java @@ -17,19 +17,19 @@ package org.neo4j.driver.internal.async; import java.util.Objects; +import org.neo4j.bolt.connection.summary.BeginSummary; +import org.neo4j.bolt.connection.summary.CommitSummary; +import org.neo4j.bolt.connection.summary.LogoffSummary; +import org.neo4j.bolt.connection.summary.LogonSummary; +import org.neo4j.bolt.connection.summary.ResetSummary; +import org.neo4j.bolt.connection.summary.RollbackSummary; +import org.neo4j.bolt.connection.summary.RouteSummary; +import org.neo4j.bolt.connection.summary.RunSummary; +import org.neo4j.bolt.connection.summary.TelemetrySummary; import org.neo4j.driver.Value; import org.neo4j.driver.internal.adaptedbolt.DriverResponseHandler; import org.neo4j.driver.internal.adaptedbolt.summary.DiscardSummary; import org.neo4j.driver.internal.adaptedbolt.summary.PullSummary; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.CommitSummary; -import org.neo4j.driver.internal.bolt.api.summary.LogoffSummary; -import org.neo4j.driver.internal.bolt.api.summary.LogonSummary; -import org.neo4j.driver.internal.bolt.api.summary.ResetSummary; -import org.neo4j.driver.internal.bolt.api.summary.RollbackSummary; -import org.neo4j.driver.internal.bolt.api.summary.RouteSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.summary.TelemetrySummary; abstract class DelegatingResponseHandler implements DriverResponseHandler { protected final DriverResponseHandler delegate; diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/InternalAsyncSession.java b/driver/src/main/java/org/neo4j/driver/internal/async/InternalAsyncSession.java index 53a34ae5ae..6004605123 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/InternalAsyncSession.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/InternalAsyncSession.java @@ -24,6 +24,7 @@ import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; +import org.neo4j.bolt.connection.TelemetryApi; import org.neo4j.driver.AccessMode; import org.neo4j.driver.Bookmark; import org.neo4j.driver.Query; @@ -36,7 +37,6 @@ import org.neo4j.driver.exceptions.ClientException; import org.neo4j.driver.internal.GqlStatusError; import org.neo4j.driver.internal.InternalBookmark; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; import org.neo4j.driver.internal.telemetry.ApiTelemetryWork; import org.neo4j.driver.internal.util.Futures; diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/LeakLoggingNetworkSession.java b/driver/src/main/java/org/neo4j/driver/internal/async/LeakLoggingNetworkSession.java index 72224fff1c..66ed27a663 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/LeakLoggingNetworkSession.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/LeakLoggingNetworkSession.java @@ -21,6 +21,7 @@ import java.util.Arrays; import java.util.Set; import java.util.stream.Collectors; +import org.neo4j.bolt.connection.DatabaseName; import org.neo4j.driver.AccessMode; import org.neo4j.driver.AuthToken; import org.neo4j.driver.AuthTokenManager; @@ -29,7 +30,6 @@ import org.neo4j.driver.Logging; import org.neo4j.driver.NotificationConfig; import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnectionProvider; -import org.neo4j.driver.internal.bolt.api.DatabaseName; import org.neo4j.driver.internal.homedb.HomeDatabaseCache; import org.neo4j.driver.internal.retry.RetryLogic; import org.neo4j.driver.internal.security.BoltSecurityPlanManager; diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/NetworkSession.java b/driver/src/main/java/org/neo4j/driver/internal/async/NetworkSession.java index a4d5f1b348..d53224cd6e 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/NetworkSession.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/NetworkSession.java @@ -35,6 +35,14 @@ import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.DatabaseName; +import org.neo4j.bolt.connection.DatabaseNameUtil; +import org.neo4j.bolt.connection.NotificationConfig; +import org.neo4j.bolt.connection.SecurityPlan; +import org.neo4j.bolt.connection.TelemetryApi; +import org.neo4j.bolt.connection.exception.MinVersionAcquisitionException; +import org.neo4j.bolt.connection.summary.RunSummary; import org.neo4j.driver.AccessMode; import org.neo4j.driver.AuthToken; import org.neo4j.driver.AuthTokenManager; @@ -59,14 +67,6 @@ import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnection; import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnectionProvider; import org.neo4j.driver.internal.adaptedbolt.DriverResponseHandler; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.DatabaseNameUtil; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; -import org.neo4j.driver.internal.bolt.api.exception.MinVersionAcquisitionException; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; import org.neo4j.driver.internal.cursor.DisposableResultCursorImpl; import org.neo4j.driver.internal.cursor.ResultCursorImpl; import org.neo4j.driver.internal.cursor.RxResultCursor; @@ -654,10 +654,10 @@ private static Supplier>> tokenStageSupplier( : () -> authTokenManager.getToken().thenApply(token -> ((InternalAuthToken) token).toMap()); } - private static org.neo4j.driver.internal.bolt.api.AccessMode asBoltAccessMode(AccessMode mode) { + private static org.neo4j.bolt.connection.AccessMode asBoltAccessMode(AccessMode mode) { return switch (mode) { - case WRITE -> org.neo4j.driver.internal.bolt.api.AccessMode.WRITE; - case READ -> org.neo4j.driver.internal.bolt.api.AccessMode.READ; + case WRITE -> org.neo4j.bolt.connection.AccessMode.WRITE; + case READ -> org.neo4j.bolt.connection.AccessMode.READ; }; } diff --git a/driver/src/main/java/org/neo4j/driver/internal/async/UnmanagedTransaction.java b/driver/src/main/java/org/neo4j/driver/internal/async/UnmanagedTransaction.java index ccdca148a8..71c5130228 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/async/UnmanagedTransaction.java +++ b/driver/src/main/java/org/neo4j/driver/internal/async/UnmanagedTransaction.java @@ -35,6 +35,14 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Collectors; +import org.neo4j.bolt.connection.AccessMode; +import org.neo4j.bolt.connection.DatabaseName; +import org.neo4j.bolt.connection.NotificationConfig; +import org.neo4j.bolt.connection.TransactionType; +import org.neo4j.bolt.connection.summary.BeginSummary; +import org.neo4j.bolt.connection.summary.CommitSummary; +import org.neo4j.bolt.connection.summary.RunSummary; +import org.neo4j.bolt.connection.summary.TelemetrySummary; import org.neo4j.driver.Bookmark; import org.neo4j.driver.Logging; import org.neo4j.driver.Query; @@ -49,14 +57,6 @@ import org.neo4j.driver.internal.adaptedbolt.BasicResponseHandler; import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnection; import org.neo4j.driver.internal.adaptedbolt.DriverResponseHandler; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.TransactionType; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.CommitSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.summary.TelemetrySummary; import org.neo4j.driver.internal.cursor.DisposableResultCursorImpl; import org.neo4j.driver.internal.cursor.ResultCursorImpl; import org.neo4j.driver.internal.cursor.RxResultCursor; diff --git a/driver/src/main/java/org/neo4j/driver/internal/boltlistener/BoltConnectionListener.java b/driver/src/main/java/org/neo4j/driver/internal/boltlistener/BoltConnectionListener.java index 06cc4787f8..3bf7db3b03 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/boltlistener/BoltConnectionListener.java +++ b/driver/src/main/java/org/neo4j/driver/internal/boltlistener/BoltConnectionListener.java @@ -16,8 +16,8 @@ */ package org.neo4j.driver.internal.boltlistener; -import org.neo4j.driver.internal.bolt.api.BoltConnection; -import org.neo4j.driver.internal.bolt.api.BoltConnectionProvider; +import org.neo4j.bolt.connection.BoltConnection; +import org.neo4j.bolt.connection.BoltConnectionProvider; public interface BoltConnectionListener { void onOpen(BoltConnection boltConnection); diff --git a/driver/src/main/java/org/neo4j/driver/internal/boltlistener/ListeningBoltConnection.java b/driver/src/main/java/org/neo4j/driver/internal/boltlistener/ListeningBoltConnection.java index 7c67a3fe7c..3a6548ae86 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/boltlistener/ListeningBoltConnection.java +++ b/driver/src/main/java/org/neo4j/driver/internal/boltlistener/ListeningBoltConnection.java @@ -22,19 +22,19 @@ import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletionStage; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.AuthInfo; -import org.neo4j.driver.internal.bolt.api.AuthToken; -import org.neo4j.driver.internal.bolt.api.BoltConnection; -import org.neo4j.driver.internal.bolt.api.BoltConnectionState; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.ResponseHandler; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; -import org.neo4j.driver.internal.bolt.api.TransactionType; -import org.neo4j.driver.internal.bolt.api.values.Value; +import org.neo4j.bolt.connection.AccessMode; +import org.neo4j.bolt.connection.AuthInfo; +import org.neo4j.bolt.connection.AuthToken; +import org.neo4j.bolt.connection.BoltConnection; +import org.neo4j.bolt.connection.BoltConnectionState; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.BoltServerAddress; +import org.neo4j.bolt.connection.DatabaseName; +import org.neo4j.bolt.connection.NotificationConfig; +import org.neo4j.bolt.connection.ResponseHandler; +import org.neo4j.bolt.connection.TelemetryApi; +import org.neo4j.bolt.connection.TransactionType; +import org.neo4j.bolt.connection.values.Value; final class ListeningBoltConnection implements BoltConnection { private final BoltConnection delegate; diff --git a/driver/src/main/java/org/neo4j/driver/internal/boltlistener/ListeningBoltConnectionProvider.java b/driver/src/main/java/org/neo4j/driver/internal/boltlistener/ListeningBoltConnectionProvider.java index 0456311b59..f103a4c5a1 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/boltlistener/ListeningBoltConnectionProvider.java +++ b/driver/src/main/java/org/neo4j/driver/internal/boltlistener/ListeningBoltConnectionProvider.java @@ -22,17 +22,17 @@ import java.util.concurrent.CompletionStage; import java.util.function.Consumer; import java.util.function.Supplier; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.AuthToken; -import org.neo4j.driver.internal.bolt.api.BoltAgent; -import org.neo4j.driver.internal.bolt.api.BoltConnection; -import org.neo4j.driver.internal.bolt.api.BoltConnectionProvider; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.NotificationConfig; -import org.neo4j.driver.internal.bolt.api.RoutingContext; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; +import org.neo4j.bolt.connection.AccessMode; +import org.neo4j.bolt.connection.AuthToken; +import org.neo4j.bolt.connection.BoltAgent; +import org.neo4j.bolt.connection.BoltConnection; +import org.neo4j.bolt.connection.BoltConnectionProvider; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.BoltServerAddress; +import org.neo4j.bolt.connection.DatabaseName; +import org.neo4j.bolt.connection.NotificationConfig; +import org.neo4j.bolt.connection.RoutingContext; +import org.neo4j.bolt.connection.SecurityPlan; final class ListeningBoltConnectionProvider implements BoltConnectionProvider { private final BoltConnectionProvider delegate; diff --git a/driver/src/main/java/org/neo4j/driver/internal/cursor/ResultCursorImpl.java b/driver/src/main/java/org/neo4j/driver/internal/cursor/ResultCursorImpl.java index 4ef7785aaa..3d4b880cbc 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/cursor/ResultCursorImpl.java +++ b/driver/src/main/java/org/neo4j/driver/internal/cursor/ResultCursorImpl.java @@ -28,6 +28,10 @@ import java.util.concurrent.CompletionStage; import java.util.function.Consumer; import java.util.function.Function; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.summary.BeginSummary; +import org.neo4j.bolt.connection.summary.RunSummary; +import org.neo4j.bolt.connection.summary.TelemetrySummary; import org.neo4j.driver.Bookmark; import org.neo4j.driver.Query; import org.neo4j.driver.Record; @@ -45,10 +49,6 @@ import org.neo4j.driver.internal.adaptedbolt.summary.DiscardSummary; import org.neo4j.driver.internal.adaptedbolt.summary.PullSummary; import org.neo4j.driver.internal.async.UnmanagedTransaction; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; -import org.neo4j.driver.internal.bolt.api.summary.TelemetrySummary; import org.neo4j.driver.internal.telemetry.ApiTelemetryWork; import org.neo4j.driver.internal.util.Futures; import org.neo4j.driver.internal.util.MetadataExtractor; diff --git a/driver/src/main/java/org/neo4j/driver/internal/cursor/RxResultCursorImpl.java b/driver/src/main/java/org/neo4j/driver/internal/cursor/RxResultCursorImpl.java index dc9d8066f7..d0e71f5138 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/cursor/RxResultCursorImpl.java +++ b/driver/src/main/java/org/neo4j/driver/internal/cursor/RxResultCursorImpl.java @@ -28,6 +28,8 @@ import java.util.concurrent.CompletionStage; import java.util.function.BiConsumer; import java.util.function.Consumer; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.summary.RunSummary; import org.neo4j.driver.Bookmark; import org.neo4j.driver.Logger; import org.neo4j.driver.Logging; @@ -44,8 +46,6 @@ import org.neo4j.driver.internal.adaptedbolt.DriverResponseHandler; import org.neo4j.driver.internal.adaptedbolt.summary.DiscardSummary; import org.neo4j.driver.internal.adaptedbolt.summary.PullSummary; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; import org.neo4j.driver.internal.util.Futures; import org.neo4j.driver.internal.util.MetadataExtractor; import org.neo4j.driver.summary.GqlStatusObject; diff --git a/driver/src/main/java/org/neo4j/driver/internal/homedb/HomeDatabaseCacheImpl.java b/driver/src/main/java/org/neo4j/driver/internal/homedb/HomeDatabaseCacheImpl.java index 831f17dadc..3146f26019 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/homedb/HomeDatabaseCacheImpl.java +++ b/driver/src/main/java/org/neo4j/driver/internal/homedb/HomeDatabaseCacheImpl.java @@ -24,7 +24,7 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; -import org.neo4j.driver.internal.bolt.api.BoltConnection; +import org.neo4j.bolt.connection.BoltConnection; final class HomeDatabaseCacheImpl implements HomeDatabaseCache { private final Map keyToEntry = new HashMap<>(); diff --git a/driver/src/main/java/org/neo4j/driver/internal/homedb/NoopHomeDatabaseCache.java b/driver/src/main/java/org/neo4j/driver/internal/homedb/NoopHomeDatabaseCache.java index f23f763194..dda99e86ab 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/homedb/NoopHomeDatabaseCache.java +++ b/driver/src/main/java/org/neo4j/driver/internal/homedb/NoopHomeDatabaseCache.java @@ -17,7 +17,7 @@ package org.neo4j.driver.internal.homedb; import java.util.Optional; -import org.neo4j.driver.internal.bolt.api.BoltConnection; +import org.neo4j.bolt.connection.BoltConnection; final class NoopHomeDatabaseCache implements HomeDatabaseCache { @Override diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/ConnectionPoolMetricsListener.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/ConnectionPoolMetricsListener.java index 6933d9e916..ad9fc33fa6 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/ConnectionPoolMetricsListener.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/ConnectionPoolMetricsListener.java @@ -16,7 +16,7 @@ */ package org.neo4j.driver.internal.metrics; -import org.neo4j.driver.internal.bolt.api.ListenerEvent; +import org.neo4j.bolt.connection.ListenerEvent; interface ConnectionPoolMetricsListener { /** diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/DevNullListenerEvent.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/DevNullListenerEvent.java index db2e2802fb..0a9a3a812c 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/DevNullListenerEvent.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/DevNullListenerEvent.java @@ -16,7 +16,7 @@ */ package org.neo4j.driver.internal.metrics; -import org.neo4j.driver.internal.bolt.api.ListenerEvent; +import org.neo4j.bolt.connection.ListenerEvent; enum DevNullListenerEvent implements ListenerEvent { INSTANCE; diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/DevNullMetricsListener.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/DevNullMetricsListener.java index e59a592e54..8112c0975c 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/DevNullMetricsListener.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/DevNullMetricsListener.java @@ -17,9 +17,9 @@ package org.neo4j.driver.internal.metrics; import java.util.function.IntSupplier; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.ListenerEvent; -import org.neo4j.driver.internal.bolt.api.MetricsListener; +import org.neo4j.bolt.connection.BoltServerAddress; +import org.neo4j.bolt.connection.ListenerEvent; +import org.neo4j.bolt.connection.MetricsListener; public enum DevNullMetricsListener implements MetricsListener { INSTANCE; diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/DevNullMetricsProvider.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/DevNullMetricsProvider.java index 70c9365669..903039bb12 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/DevNullMetricsProvider.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/DevNullMetricsProvider.java @@ -16,10 +16,10 @@ */ package org.neo4j.driver.internal.metrics; +import org.neo4j.bolt.connection.MetricsListener; import org.neo4j.driver.Metrics; import org.neo4j.driver.exceptions.ClientException; import org.neo4j.driver.internal.GqlStatusError; -import org.neo4j.driver.internal.bolt.api.MetricsListener; public enum DevNullMetricsProvider implements MetricsProvider { INSTANCE; diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/DevNullPoolMetricsListener.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/DevNullPoolMetricsListener.java index f4cb64e851..945237acf0 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/DevNullPoolMetricsListener.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/DevNullPoolMetricsListener.java @@ -16,7 +16,7 @@ */ package org.neo4j.driver.internal.metrics; -import org.neo4j.driver.internal.bolt.api.ListenerEvent; +import org.neo4j.bolt.connection.ListenerEvent; enum DevNullPoolMetricsListener implements ConnectionPoolMetricsListener { INSTANCE; diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java index 8538ceef31..1ca179f509 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalConnectionPoolMetrics.java @@ -22,9 +22,9 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.function.IntSupplier; +import org.neo4j.bolt.connection.BoltServerAddress; +import org.neo4j.bolt.connection.ListenerEvent; import org.neo4j.driver.ConnectionPoolMetrics; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.ListenerEvent; final class InternalConnectionPoolMetrics implements ConnectionPoolMetrics, ConnectionPoolMetricsListener { private final BoltServerAddress address; diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalMetrics.java index c2f57899fe..79e15e8650 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalMetrics.java @@ -25,13 +25,13 @@ import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.function.IntSupplier; +import org.neo4j.bolt.connection.BoltServerAddress; +import org.neo4j.bolt.connection.ListenerEvent; +import org.neo4j.bolt.connection.MetricsListener; import org.neo4j.driver.ConnectionPoolMetrics; import org.neo4j.driver.Logger; import org.neo4j.driver.Logging; import org.neo4j.driver.Metrics; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.ListenerEvent; -import org.neo4j.driver.internal.bolt.api.MetricsListener; final class InternalMetrics implements Metrics, MetricsListener { private final Map connectionPoolMetrics; diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalMetricsProvider.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalMetricsProvider.java index 96bb2f39e3..655695fd83 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalMetricsProvider.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/InternalMetricsProvider.java @@ -17,9 +17,9 @@ package org.neo4j.driver.internal.metrics; import java.time.Clock; +import org.neo4j.bolt.connection.MetricsListener; import org.neo4j.driver.Logging; import org.neo4j.driver.Metrics; -import org.neo4j.driver.internal.bolt.api.MetricsListener; public final class InternalMetricsProvider implements MetricsProvider { private final InternalMetrics metrics; diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/MetricsProvider.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/MetricsProvider.java index 49f5a6efe6..fa27257b09 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/MetricsProvider.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/MetricsProvider.java @@ -16,8 +16,8 @@ */ package org.neo4j.driver.internal.metrics; +import org.neo4j.bolt.connection.MetricsListener; import org.neo4j.driver.Metrics; -import org.neo4j.driver.internal.bolt.api.MetricsListener; /** * An adapter that collects driver metrics via {@link MetricsListener} and publishes them via {@link Metrics} instance. diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/MicrometerConnectionPoolMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/MicrometerConnectionPoolMetrics.java index 2e3a41d59a..6efa483d59 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/MicrometerConnectionPoolMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/MicrometerConnectionPoolMetrics.java @@ -28,9 +28,9 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.IntSupplier; +import org.neo4j.bolt.connection.BoltServerAddress; +import org.neo4j.bolt.connection.ListenerEvent; import org.neo4j.driver.ConnectionPoolMetrics; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.ListenerEvent; final class MicrometerConnectionPoolMetrics implements ConnectionPoolMetricsListener, ConnectionPoolMetrics { public static final String PREFIX = "neo4j.driver.connections"; diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/MicrometerMetrics.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/MicrometerMetrics.java index b89e2d38e2..17d14edd18 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/MicrometerMetrics.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/MicrometerMetrics.java @@ -22,11 +22,11 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.function.IntSupplier; +import org.neo4j.bolt.connection.BoltServerAddress; +import org.neo4j.bolt.connection.ListenerEvent; +import org.neo4j.bolt.connection.MetricsListener; import org.neo4j.driver.ConnectionPoolMetrics; import org.neo4j.driver.Metrics; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.ListenerEvent; -import org.neo4j.driver.internal.bolt.api.MetricsListener; final class MicrometerMetrics implements Metrics, MetricsListener { private final MeterRegistry meterRegistry; diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/MicrometerMetricsProvider.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/MicrometerMetricsProvider.java index fce75c08aa..5e0202407c 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/MicrometerMetricsProvider.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/MicrometerMetricsProvider.java @@ -17,8 +17,8 @@ package org.neo4j.driver.internal.metrics; import io.micrometer.core.instrument.MeterRegistry; +import org.neo4j.bolt.connection.MetricsListener; import org.neo4j.driver.Metrics; -import org.neo4j.driver.internal.bolt.api.MetricsListener; /** * An adapter to bridge between driver metrics and Micrometer {@link MeterRegistry meter registry}. diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/MicrometerTimerListenerEvent.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/MicrometerTimerListenerEvent.java index cec39a1670..465031fb28 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/MicrometerTimerListenerEvent.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/MicrometerTimerListenerEvent.java @@ -18,7 +18,7 @@ import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Timer; -import org.neo4j.driver.internal.bolt.api.ListenerEvent; +import org.neo4j.bolt.connection.ListenerEvent; final class MicrometerTimerListenerEvent implements ListenerEvent { private final MeterRegistry meterRegistry; diff --git a/driver/src/main/java/org/neo4j/driver/internal/metrics/TimeRecorderListenerEvent.java b/driver/src/main/java/org/neo4j/driver/internal/metrics/TimeRecorderListenerEvent.java index 20843bcbde..cfc2a2bf30 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/metrics/TimeRecorderListenerEvent.java +++ b/driver/src/main/java/org/neo4j/driver/internal/metrics/TimeRecorderListenerEvent.java @@ -17,7 +17,7 @@ package org.neo4j.driver.internal.metrics; import java.time.Clock; -import org.neo4j.driver.internal.bolt.api.ListenerEvent; +import org.neo4j.bolt.connection.ListenerEvent; final class TimeRecorderListenerEvent implements ListenerEvent { private final Clock clock; diff --git a/driver/src/main/java/org/neo4j/driver/internal/reactive/AbstractReactiveSession.java b/driver/src/main/java/org/neo4j/driver/internal/reactive/AbstractReactiveSession.java index 26d1eb890c..92986edf88 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/reactive/AbstractReactiveSession.java +++ b/driver/src/main/java/org/neo4j/driver/internal/reactive/AbstractReactiveSession.java @@ -25,6 +25,7 @@ import java.util.concurrent.CompletionStage; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; +import org.neo4j.bolt.connection.TelemetryApi; import org.neo4j.driver.AccessMode; import org.neo4j.driver.Bookmark; import org.neo4j.driver.Query; @@ -34,7 +35,6 @@ import org.neo4j.driver.internal.GqlStatusError; import org.neo4j.driver.internal.async.NetworkSession; import org.neo4j.driver.internal.async.UnmanagedTransaction; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; import org.neo4j.driver.internal.cursor.RxResultCursor; import org.neo4j.driver.internal.telemetry.ApiTelemetryWork; import org.neo4j.driver.internal.util.Futures; diff --git a/driver/src/main/java/org/neo4j/driver/internal/reactive/InternalReactiveSession.java b/driver/src/main/java/org/neo4j/driver/internal/reactive/InternalReactiveSession.java index ee0985f0a8..aefb44b161 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/reactive/InternalReactiveSession.java +++ b/driver/src/main/java/org/neo4j/driver/internal/reactive/InternalReactiveSession.java @@ -22,13 +22,13 @@ import java.util.HashSet; import java.util.Set; import java.util.concurrent.Flow.Publisher; +import org.neo4j.bolt.connection.TelemetryApi; import org.neo4j.driver.AccessMode; import org.neo4j.driver.Bookmark; import org.neo4j.driver.Query; import org.neo4j.driver.TransactionConfig; import org.neo4j.driver.internal.async.NetworkSession; import org.neo4j.driver.internal.async.UnmanagedTransaction; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; import org.neo4j.driver.internal.telemetry.ApiTelemetryWork; import org.neo4j.driver.reactive.ReactiveResult; import org.neo4j.driver.reactive.ReactiveSession; diff --git a/driver/src/main/java/org/neo4j/driver/internal/reactive/InternalRxSession.java b/driver/src/main/java/org/neo4j/driver/internal/reactive/InternalRxSession.java index b61e222fbd..7882cbe68a 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/reactive/InternalRxSession.java +++ b/driver/src/main/java/org/neo4j/driver/internal/reactive/InternalRxSession.java @@ -18,6 +18,7 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; +import org.neo4j.bolt.connection.TelemetryApi; import org.neo4j.driver.AccessMode; import org.neo4j.driver.Bookmark; import org.neo4j.driver.Query; @@ -26,7 +27,6 @@ import org.neo4j.driver.internal.InternalBookmark; import org.neo4j.driver.internal.async.NetworkSession; import org.neo4j.driver.internal.async.UnmanagedTransaction; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; import org.neo4j.driver.internal.cursor.RxResultCursor; import org.neo4j.driver.internal.telemetry.ApiTelemetryWork; import org.neo4j.driver.internal.util.Futures; diff --git a/driver/src/main/java/org/neo4j/driver/internal/reactivestreams/InternalReactiveSession.java b/driver/src/main/java/org/neo4j/driver/internal/reactivestreams/InternalReactiveSession.java index 54863df9ff..05006b09c7 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/reactivestreams/InternalReactiveSession.java +++ b/driver/src/main/java/org/neo4j/driver/internal/reactivestreams/InternalReactiveSession.java @@ -18,13 +18,13 @@ import java.util.HashSet; import java.util.Set; +import org.neo4j.bolt.connection.TelemetryApi; import org.neo4j.driver.AccessMode; import org.neo4j.driver.Bookmark; import org.neo4j.driver.Query; import org.neo4j.driver.TransactionConfig; import org.neo4j.driver.internal.async.NetworkSession; import org.neo4j.driver.internal.async.UnmanagedTransaction; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; import org.neo4j.driver.internal.reactive.AbstractReactiveSession; import org.neo4j.driver.internal.telemetry.ApiTelemetryWork; import org.neo4j.driver.reactivestreams.ReactiveResult; diff --git a/driver/src/main/java/org/neo4j/driver/internal/security/BoltSecurityPlanManager.java b/driver/src/main/java/org/neo4j/driver/internal/security/BoltSecurityPlanManager.java index a82d800d26..38ffe1dce4 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/security/BoltSecurityPlanManager.java +++ b/driver/src/main/java/org/neo4j/driver/internal/security/BoltSecurityPlanManager.java @@ -17,7 +17,7 @@ package org.neo4j.driver.internal.security; import java.util.concurrent.CompletionStage; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; +import org.neo4j.bolt.connection.SecurityPlan; public interface BoltSecurityPlanManager { CompletionStage plan(); diff --git a/driver/src/main/java/org/neo4j/driver/internal/security/InternalBoltSecurityPlanManager.java b/driver/src/main/java/org/neo4j/driver/internal/security/InternalBoltSecurityPlanManager.java index f61d290be2..91f3951a49 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/security/InternalBoltSecurityPlanManager.java +++ b/driver/src/main/java/org/neo4j/driver/internal/security/InternalBoltSecurityPlanManager.java @@ -17,8 +17,8 @@ package org.neo4j.driver.internal.security; import java.util.concurrent.CompletionStage; -import org.neo4j.driver.internal.bolt.api.SecurityPlan; -import org.neo4j.driver.internal.bolt.api.SecurityPlans; +import org.neo4j.bolt.connection.SecurityPlan; +import org.neo4j.bolt.connection.SecurityPlans; public class InternalBoltSecurityPlanManager implements BoltSecurityPlanManager { private final org.neo4j.driver.internal.security.SecurityPlan securityPlan; @@ -32,7 +32,7 @@ public CompletionStage plan() { return securityPlan .sslContext() .thenApply(sslContext -> securityPlan.requiresEncryption() - ? org.neo4j.driver.internal.bolt.api.SecurityPlans.encrypted( + ? org.neo4j.bolt.connection.SecurityPlans.encrypted( securityPlan.requiresClientAuth(), sslContext, securityPlan.requiresHostnameVerification()) diff --git a/driver/src/main/java/org/neo4j/driver/internal/security/SecurityPlanImpl.java b/driver/src/main/java/org/neo4j/driver/internal/security/SecurityPlanImpl.java index 219461aa15..8080c07ee5 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/security/SecurityPlanImpl.java +++ b/driver/src/main/java/org/neo4j/driver/internal/security/SecurityPlanImpl.java @@ -25,11 +25,11 @@ import java.util.concurrent.CompletionStage; import java.util.function.Supplier; import javax.net.ssl.SSLContext; +import org.neo4j.bolt.connection.ssl.SSLContexts; +import org.neo4j.bolt.connection.ssl.TrustManagerFactories; import org.neo4j.driver.ClientCertificateManager; import org.neo4j.driver.Logging; import org.neo4j.driver.RevocationCheckingStrategy; -import org.neo4j.driver.internal.bolt.api.ssl.SSLContexts; -import org.neo4j.driver.internal.bolt.api.ssl.TrustManagerFactories; import org.neo4j.driver.internal.util.Futures; /** @@ -140,13 +140,12 @@ public RevocationCheckingStrategy revocationCheckingStrategy() { return revocationCheckingStrategy; } - private static org.neo4j.driver.internal.bolt.api.ssl.RevocationCheckingStrategy map( + private static org.neo4j.bolt.connection.ssl.RevocationCheckingStrategy map( RevocationCheckingStrategy revocationCheckingStrategy) { return switch (revocationCheckingStrategy) { - case NO_CHECKS -> org.neo4j.driver.internal.bolt.api.ssl.RevocationCheckingStrategy.NO_CHECKS; - case VERIFY_IF_PRESENT -> org.neo4j.driver.internal.bolt.api.ssl.RevocationCheckingStrategy - .VERIFY_IF_PRESENT; - case STRICT -> org.neo4j.driver.internal.bolt.api.ssl.RevocationCheckingStrategy.STRICT; + case NO_CHECKS -> org.neo4j.bolt.connection.ssl.RevocationCheckingStrategy.NO_CHECKS; + case VERIFY_IF_PRESENT -> org.neo4j.bolt.connection.ssl.RevocationCheckingStrategy.VERIFY_IF_PRESENT; + case STRICT -> org.neo4j.bolt.connection.ssl.RevocationCheckingStrategy.STRICT; }; } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/summary/InternalServerInfo.java b/driver/src/main/java/org/neo4j/driver/internal/summary/InternalServerInfo.java index 9b2205993a..c2ce823f23 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/summary/InternalServerInfo.java +++ b/driver/src/main/java/org/neo4j/driver/internal/summary/InternalServerInfo.java @@ -17,8 +17,8 @@ package org.neo4j.driver.internal.summary; import java.util.Objects; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.BoltServerAddress; import org.neo4j.driver.summary.ServerInfo; public class InternalServerInfo implements ServerInfo { diff --git a/driver/src/main/java/org/neo4j/driver/internal/telemetry/ApiTelemetryWork.java b/driver/src/main/java/org/neo4j/driver/internal/telemetry/ApiTelemetryWork.java index a170e9f2a1..f2c4afcdc5 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/telemetry/ApiTelemetryWork.java +++ b/driver/src/main/java/org/neo4j/driver/internal/telemetry/ApiTelemetryWork.java @@ -20,8 +20,8 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.atomic.AtomicBoolean; +import org.neo4j.bolt.connection.TelemetryApi; import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnection; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; public record ApiTelemetryWork(TelemetryApi telemetryApi, AtomicBoolean enabled, AtomicBoolean acknowledged) { public ApiTelemetryWork(TelemetryApi telemetryApi) { diff --git a/driver/src/main/java/org/neo4j/driver/internal/util/DriverInfoUtil.java b/driver/src/main/java/org/neo4j/driver/internal/util/DriverInfoUtil.java index 57d85e354b..d215a7c74d 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/util/DriverInfoUtil.java +++ b/driver/src/main/java/org/neo4j/driver/internal/util/DriverInfoUtil.java @@ -19,8 +19,8 @@ import static java.lang.String.format; import java.util.Optional; +import org.neo4j.bolt.connection.BoltAgent; import org.neo4j.driver.Session; -import org.neo4j.driver.internal.bolt.api.BoltAgent; public class DriverInfoUtil { public static BoltAgent boltAgent() { diff --git a/driver/src/main/java/org/neo4j/driver/internal/util/Futures.java b/driver/src/main/java/org/neo4j/driver/internal/util/Futures.java index 2141955de7..60f0fbc1cd 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/util/Futures.java +++ b/driver/src/main/java/org/neo4j/driver/internal/util/Futures.java @@ -26,7 +26,7 @@ import java.util.concurrent.Future; import java.util.function.BiConsumer; import java.util.function.BiFunction; -import org.neo4j.driver.internal.bolt.basicimpl.EventLoopThread; +import org.neo4j.bolt.connection.netty.EventLoopThread; public final class Futures { private static final CompletableFuture COMPLETED_WITH_NULL = completedFuture(null); diff --git a/driver/src/main/java/org/neo4j/driver/internal/value/BoltValue.java b/driver/src/main/java/org/neo4j/driver/internal/value/BoltValue.java index b75e2d95c5..e1b813bc8f 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/value/BoltValue.java +++ b/driver/src/main/java/org/neo4j/driver/internal/value/BoltValue.java @@ -25,16 +25,16 @@ import java.util.Map; import java.util.Objects; import java.util.function.Function; +import org.neo4j.bolt.connection.values.IsoDuration; +import org.neo4j.bolt.connection.values.Point; +import org.neo4j.bolt.connection.values.Type; +import org.neo4j.bolt.connection.values.Value; import org.neo4j.driver.exceptions.value.Uncoercible; import org.neo4j.driver.internal.InternalIsoDuration; import org.neo4j.driver.internal.InternalPoint2D; import org.neo4j.driver.internal.InternalPoint3D; -import org.neo4j.driver.internal.bolt.api.values.IsoDuration; -import org.neo4j.driver.internal.bolt.api.values.Point; -import org.neo4j.driver.internal.bolt.api.values.Type; -import org.neo4j.driver.internal.bolt.api.values.Value; -public class BoltValue implements org.neo4j.driver.internal.bolt.api.values.Value { +public class BoltValue implements org.neo4j.bolt.connection.values.Value { private final InternalValue value; private final Type type; @@ -139,12 +139,12 @@ public int size() { } @Override - public org.neo4j.driver.internal.bolt.api.values.Value get(String key) { + public org.neo4j.bolt.connection.values.Value get(String key) { return ((InternalValue) value.get(key)).asBoltValue(); } @Override - public Iterable values() { + public Iterable values() { return () -> new Iterator<>() { private final Iterator iterator = value.values().iterator(); @@ -167,7 +167,7 @@ public boolean containsKey(String key) { } @Override - public Map asMap(Function mapFunction) { + public Map asMap(Function mapFunction) { return value.asMap(v -> mapFunction.apply(((InternalValue) v).asBoltValue())); } diff --git a/driver/src/main/java/org/neo4j/driver/internal/value/BoltValueFactory.java b/driver/src/main/java/org/neo4j/driver/internal/value/BoltValueFactory.java index 08324c7e6c..3fcb7084b6 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/value/BoltValueFactory.java +++ b/driver/src/main/java/org/neo4j/driver/internal/value/BoltValueFactory.java @@ -22,16 +22,16 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.neo4j.bolt.connection.values.Node; +import org.neo4j.bolt.connection.values.Path; +import org.neo4j.bolt.connection.values.Relationship; +import org.neo4j.bolt.connection.values.Segment; +import org.neo4j.bolt.connection.values.Value; +import org.neo4j.bolt.connection.values.ValueFactory; import org.neo4j.driver.Values; import org.neo4j.driver.internal.InternalNode; import org.neo4j.driver.internal.InternalPath; import org.neo4j.driver.internal.InternalRelationship; -import org.neo4j.driver.internal.bolt.api.values.Node; -import org.neo4j.driver.internal.bolt.api.values.Path; -import org.neo4j.driver.internal.bolt.api.values.Relationship; -import org.neo4j.driver.internal.bolt.api.values.Segment; -import org.neo4j.driver.internal.bolt.api.values.Value; -import org.neo4j.driver.internal.bolt.api.values.ValueFactory; public class BoltValueFactory implements ValueFactory { private static final BoltValueFactory INSTANCE = new BoltValueFactory(); diff --git a/driver/src/main/java/org/neo4j/driver/internal/value/BooleanValue.java b/driver/src/main/java/org/neo4j/driver/internal/value/BooleanValue.java index d9d3aecd6a..96e4ee0eb4 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/value/BooleanValue.java +++ b/driver/src/main/java/org/neo4j/driver/internal/value/BooleanValue.java @@ -75,7 +75,7 @@ public String toString() { @Override public BoltValue asBoltValue() { - return new BoltValue(this, org.neo4j.driver.internal.bolt.api.values.Type.BOOLEAN); + return new BoltValue(this, org.neo4j.bolt.connection.values.Type.BOOLEAN); } } @@ -108,7 +108,7 @@ public String toString() { @Override public BoltValue asBoltValue() { - return new BoltValue(this, org.neo4j.driver.internal.bolt.api.values.Type.BOOLEAN); + return new BoltValue(this, org.neo4j.bolt.connection.values.Type.BOOLEAN); } } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/value/BytesValue.java b/driver/src/main/java/org/neo4j/driver/internal/value/BytesValue.java index a5a6fdfce4..7eff49a6d6 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/value/BytesValue.java +++ b/driver/src/main/java/org/neo4j/driver/internal/value/BytesValue.java @@ -87,6 +87,6 @@ public String toString() { @Override public BoltValue asBoltValue() { - return new BoltValue(this, org.neo4j.driver.internal.bolt.api.values.Type.BYTES); + return new BoltValue(this, org.neo4j.bolt.connection.values.Type.BYTES); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/value/DateTimeValue.java b/driver/src/main/java/org/neo4j/driver/internal/value/DateTimeValue.java index cf468b4a91..d34c46201b 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/value/DateTimeValue.java +++ b/driver/src/main/java/org/neo4j/driver/internal/value/DateTimeValue.java @@ -43,6 +43,6 @@ public Type type() { @Override public BoltValue asBoltValue() { - return new BoltValue(this, org.neo4j.driver.internal.bolt.api.values.Type.DATE_TIME); + return new BoltValue(this, org.neo4j.bolt.connection.values.Type.DATE_TIME); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/value/DateValue.java b/driver/src/main/java/org/neo4j/driver/internal/value/DateValue.java index 3e7c4dd6d1..8684ea7bff 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/value/DateValue.java +++ b/driver/src/main/java/org/neo4j/driver/internal/value/DateValue.java @@ -37,6 +37,6 @@ public Type type() { @Override public BoltValue asBoltValue() { - return new BoltValue(this, org.neo4j.driver.internal.bolt.api.values.Type.DATE); + return new BoltValue(this, org.neo4j.bolt.connection.values.Type.DATE); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/value/DurationValue.java b/driver/src/main/java/org/neo4j/driver/internal/value/DurationValue.java index aef301b698..f20fa193b0 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/value/DurationValue.java +++ b/driver/src/main/java/org/neo4j/driver/internal/value/DurationValue.java @@ -37,6 +37,6 @@ public Type type() { @Override public BoltValue asBoltValue() { - return new BoltValue(this, org.neo4j.driver.internal.bolt.api.values.Type.DURATION); + return new BoltValue(this, org.neo4j.bolt.connection.values.Type.DURATION); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/value/FloatValue.java b/driver/src/main/java/org/neo4j/driver/internal/value/FloatValue.java index 20dc650ce6..c8856b9d79 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/value/FloatValue.java +++ b/driver/src/main/java/org/neo4j/driver/internal/value/FloatValue.java @@ -98,6 +98,6 @@ public String toString() { @Override public BoltValue asBoltValue() { - return new BoltValue(this, org.neo4j.driver.internal.bolt.api.values.Type.FLOAT); + return new BoltValue(this, org.neo4j.bolt.connection.values.Type.FLOAT); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/value/IntegerValue.java b/driver/src/main/java/org/neo4j/driver/internal/value/IntegerValue.java index e0eb6211e5..6631b2c096 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/value/IntegerValue.java +++ b/driver/src/main/java/org/neo4j/driver/internal/value/IntegerValue.java @@ -90,6 +90,6 @@ public int hashCode() { @Override public BoltValue asBoltValue() { - return new BoltValue(this, org.neo4j.driver.internal.bolt.api.values.Type.INTEGER); + return new BoltValue(this, org.neo4j.bolt.connection.values.Type.INTEGER); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/value/ListValue.java b/driver/src/main/java/org/neo4j/driver/internal/value/ListValue.java index 3985c5da35..e0ce7dce0b 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/value/ListValue.java +++ b/driver/src/main/java/org/neo4j/driver/internal/value/ListValue.java @@ -118,6 +118,6 @@ public int hashCode() { @Override public BoltValue asBoltValue() { - return new BoltValue(this, org.neo4j.driver.internal.bolt.api.values.Type.LIST); + return new BoltValue(this, org.neo4j.bolt.connection.values.Type.LIST); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/value/LocalDateTimeValue.java b/driver/src/main/java/org/neo4j/driver/internal/value/LocalDateTimeValue.java index 8ab6ca08f9..24848279a9 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/value/LocalDateTimeValue.java +++ b/driver/src/main/java/org/neo4j/driver/internal/value/LocalDateTimeValue.java @@ -37,6 +37,6 @@ public Type type() { @Override public BoltValue asBoltValue() { - return new BoltValue(this, org.neo4j.driver.internal.bolt.api.values.Type.LOCAL_DATE_TIME); + return new BoltValue(this, org.neo4j.bolt.connection.values.Type.LOCAL_DATE_TIME); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/value/LocalTimeValue.java b/driver/src/main/java/org/neo4j/driver/internal/value/LocalTimeValue.java index 31ada4eb41..c389410168 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/value/LocalTimeValue.java +++ b/driver/src/main/java/org/neo4j/driver/internal/value/LocalTimeValue.java @@ -37,6 +37,6 @@ public Type type() { @Override public BoltValue asBoltValue() { - return new BoltValue(this, org.neo4j.driver.internal.bolt.api.values.Type.LOCAL_TIME); + return new BoltValue(this, org.neo4j.bolt.connection.values.Type.LOCAL_TIME); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/value/MapValue.java b/driver/src/main/java/org/neo4j/driver/internal/value/MapValue.java index 2df62e3b30..d1d1cab1a2 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/value/MapValue.java +++ b/driver/src/main/java/org/neo4j/driver/internal/value/MapValue.java @@ -119,6 +119,6 @@ public int hashCode() { @Override public BoltValue asBoltValue() { - return new BoltValue(this, org.neo4j.driver.internal.bolt.api.values.Type.MAP); + return new BoltValue(this, org.neo4j.bolt.connection.values.Type.MAP); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/value/NodeValue.java b/driver/src/main/java/org/neo4j/driver/internal/value/NodeValue.java index 93d2bf4861..1615378df6 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/value/NodeValue.java +++ b/driver/src/main/java/org/neo4j/driver/internal/value/NodeValue.java @@ -37,6 +37,6 @@ public Type type() { @Override public BoltValue asBoltValue() { - return new BoltValue(this, org.neo4j.driver.internal.bolt.api.values.Type.NODE); + return new BoltValue(this, org.neo4j.bolt.connection.values.Type.NODE); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/value/NullValue.java b/driver/src/main/java/org/neo4j/driver/internal/value/NullValue.java index 23bc2f0fd3..4ec87a39fd 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/value/NullValue.java +++ b/driver/src/main/java/org/neo4j/driver/internal/value/NullValue.java @@ -63,6 +63,6 @@ public String toString() { @Override public BoltValue asBoltValue() { - return new BoltValue(this, org.neo4j.driver.internal.bolt.api.values.Type.NULL); + return new BoltValue(this, org.neo4j.bolt.connection.values.Type.NULL); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/value/PathValue.java b/driver/src/main/java/org/neo4j/driver/internal/value/PathValue.java index eb4287fa9f..f7f4037b86 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/value/PathValue.java +++ b/driver/src/main/java/org/neo4j/driver/internal/value/PathValue.java @@ -42,6 +42,6 @@ public Type type() { @Override public BoltValue asBoltValue() { - return new BoltValue(this, org.neo4j.driver.internal.bolt.api.values.Type.PATH); + return new BoltValue(this, org.neo4j.bolt.connection.values.Type.PATH); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/value/PointValue.java b/driver/src/main/java/org/neo4j/driver/internal/value/PointValue.java index a512aeea8b..172376a6f3 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/value/PointValue.java +++ b/driver/src/main/java/org/neo4j/driver/internal/value/PointValue.java @@ -37,6 +37,6 @@ public Type type() { @Override public BoltValue asBoltValue() { - return new BoltValue(this, org.neo4j.driver.internal.bolt.api.values.Type.POINT); + return new BoltValue(this, org.neo4j.bolt.connection.values.Type.POINT); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/value/RelationshipValue.java b/driver/src/main/java/org/neo4j/driver/internal/value/RelationshipValue.java index 3ec5b1260f..19683e178c 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/value/RelationshipValue.java +++ b/driver/src/main/java/org/neo4j/driver/internal/value/RelationshipValue.java @@ -37,6 +37,6 @@ public Type type() { @Override public BoltValue asBoltValue() { - return new BoltValue(this, org.neo4j.driver.internal.bolt.api.values.Type.RELATIONSHIP); + return new BoltValue(this, org.neo4j.bolt.connection.values.Type.RELATIONSHIP); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/value/StringValue.java b/driver/src/main/java/org/neo4j/driver/internal/value/StringValue.java index eb9f89d7f7..7d38eeda4f 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/value/StringValue.java +++ b/driver/src/main/java/org/neo4j/driver/internal/value/StringValue.java @@ -79,6 +79,6 @@ public int hashCode() { @Override public BoltValue asBoltValue() { - return new BoltValue(this, org.neo4j.driver.internal.bolt.api.values.Type.STRING); + return new BoltValue(this, org.neo4j.bolt.connection.values.Type.STRING); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/value/TimeValue.java b/driver/src/main/java/org/neo4j/driver/internal/value/TimeValue.java index e5e690251f..c74529f444 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/value/TimeValue.java +++ b/driver/src/main/java/org/neo4j/driver/internal/value/TimeValue.java @@ -37,6 +37,6 @@ public Type type() { @Override public BoltValue asBoltValue() { - return new BoltValue(this, org.neo4j.driver.internal.bolt.api.values.Type.TIME); + return new BoltValue(this, org.neo4j.bolt.connection.values.Type.TIME); } } diff --git a/driver/src/main/java/org/neo4j/driver/internal/value/UnsupportedDateTimeValue.java b/driver/src/main/java/org/neo4j/driver/internal/value/UnsupportedDateTimeValue.java index 1a518d29a4..27e31404c8 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/value/UnsupportedDateTimeValue.java +++ b/driver/src/main/java/org/neo4j/driver/internal/value/UnsupportedDateTimeValue.java @@ -83,6 +83,6 @@ private DateTimeException instantiateDateTimeException() { @Override public BoltValue asBoltValue() { - return new BoltValue(this, org.neo4j.driver.internal.bolt.api.values.Type.DATE_TIME); + return new BoltValue(this, org.neo4j.bolt.connection.values.Type.DATE_TIME); } } diff --git a/driver/src/main/jpms/module-info.java b/driver/src/main/jpms/module-info.java deleted file mode 100644 index 07513234b0..0000000000 --- a/driver/src/main/jpms/module-info.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [https://neo4j.com] - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * The Neo4j Java Driver module. - */ -@SuppressWarnings({"requires-automatic", "requires-transitive-automatic"}) -module org.neo4j.driver { - exports org.neo4j.driver; - exports org.neo4j.driver.async; - exports org.neo4j.driver.reactive; - exports org.neo4j.driver.reactivestreams; - exports org.neo4j.driver.types; - exports org.neo4j.driver.summary; - exports org.neo4j.driver.net; - exports org.neo4j.driver.util; - exports org.neo4j.driver.exceptions; - exports org.neo4j.driver.exceptions.value; - - requires reactor.core; - requires io.netty.common; - requires io.netty.handler; - requires io.netty.transport; - requires io.netty.buffer; - requires io.netty.codec; - requires io.netty.resolver; - requires transitive java.logging; - requires transitive org.reactivestreams; - requires static micrometer.core; - requires static org.graalvm.nativeimage; - requires static org.slf4j; - requires static java.management; - requires static reactor.blockhound; -} diff --git a/driver/src/test/java/org/neo4j/driver/ParametersTest.java b/driver/src/test/java/org/neo4j/driver/ParametersTest.java index 6f5ce744ed..e9182a2449 100644 --- a/driver/src/test/java/org/neo4j/driver/ParametersTest.java +++ b/driver/src/test/java/org/neo4j/driver/ParametersTest.java @@ -24,8 +24,8 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.mockito.Mockito.mock; +import static org.neo4j.bolt.connection.DatabaseNameUtil.defaultDatabase; import static org.neo4j.driver.Values.parameters; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING; import static org.neo4j.driver.internal.util.ValueFactory.emptyNodeValue; import static org.neo4j.driver.internal.util.ValueFactory.emptyRelationshipValue; diff --git a/driver/src/test/java/org/neo4j/driver/integration/UnmanagedTransactionIT.java b/driver/src/test/java/org/neo4j/driver/integration/UnmanagedTransactionIT.java index 87330876a4..2cc6496163 100644 --- a/driver/src/test/java/org/neo4j/driver/integration/UnmanagedTransactionIT.java +++ b/driver/src/test/java/org/neo4j/driver/integration/UnmanagedTransactionIT.java @@ -31,6 +31,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; +import org.neo4j.bolt.connection.TelemetryApi; import org.neo4j.driver.NotificationConfig; import org.neo4j.driver.Query; import org.neo4j.driver.SessionConfig; @@ -42,7 +43,6 @@ import org.neo4j.driver.internal.InternalDriver; import org.neo4j.driver.internal.async.NetworkSession; import org.neo4j.driver.internal.async.UnmanagedTransaction; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; import org.neo4j.driver.internal.telemetry.ApiTelemetryWork; import org.neo4j.driver.testutil.DatabaseExtension; import org.neo4j.driver.testutil.ParallelizableIT; diff --git a/driver/src/test/java/org/neo4j/driver/integration/reactive/InternalReactiveSessionIT.java b/driver/src/test/java/org/neo4j/driver/integration/reactive/InternalReactiveSessionIT.java index e352cda9c4..3a6b86421c 100644 --- a/driver/src/test/java/org/neo4j/driver/integration/reactive/InternalReactiveSessionIT.java +++ b/driver/src/test/java/org/neo4j/driver/integration/reactive/InternalReactiveSessionIT.java @@ -25,8 +25,8 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.NullSource; import org.junit.jupiter.params.provider.ValueSource; +import org.neo4j.bolt.connection.TelemetryApi; import org.neo4j.driver.TransactionConfig; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; import org.neo4j.driver.internal.reactive.InternalReactiveSession; import org.neo4j.driver.internal.telemetry.ApiTelemetryWork; import org.neo4j.driver.internal.util.EnabledOnNeo4jWith; diff --git a/driver/src/test/java/org/neo4j/driver/internal/CustomSecurityPlanTest.java b/driver/src/test/java/org/neo4j/driver/internal/CustomSecurityPlanTest.java index 51339cd8a8..56e02c2aa1 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/CustomSecurityPlanTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/CustomSecurityPlanTest.java @@ -67,7 +67,7 @@ void testCustomSecurityPlanUsed() { } private static class SecurityPlanCapturingDriverFactory extends DriverFactory { - final List capturedSecurityPlans = new ArrayList<>(); + final List capturedSecurityPlans = new ArrayList<>(); @Override protected InternalDriver createDriver( diff --git a/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java b/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java index 6514c5def6..7e226dd120 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java @@ -35,6 +35,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import org.neo4j.bolt.connection.netty.BootstrapFactory; import org.neo4j.driver.AuthTokenManager; import org.neo4j.driver.AuthTokens; import org.neo4j.driver.Config; @@ -45,7 +46,6 @@ import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnectionProvider; import org.neo4j.driver.internal.async.LeakLoggingNetworkSession; import org.neo4j.driver.internal.async.NetworkSession; -import org.neo4j.driver.internal.bolt.basicimpl.BootstrapFactory; import org.neo4j.driver.internal.homedb.HomeDatabaseCache; import org.neo4j.driver.internal.metrics.DevNullMetricsProvider; import org.neo4j.driver.internal.metrics.InternalMetricsProvider; diff --git a/driver/src/test/java/org/neo4j/driver/internal/InternalExecutableQueryTest.java b/driver/src/test/java/org/neo4j/driver/internal/InternalExecutableQueryTest.java index b439db6541..80d17ec4d7 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/InternalExecutableQueryTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/InternalExecutableQueryTest.java @@ -35,6 +35,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.ArgumentCaptor; +import org.neo4j.bolt.connection.TelemetryApi; import org.neo4j.driver.AccessMode; import org.neo4j.driver.AuthTokens; import org.neo4j.driver.BookmarkManager; @@ -50,7 +51,6 @@ import org.neo4j.driver.TransactionCallback; import org.neo4j.driver.TransactionConfig; import org.neo4j.driver.TransactionContext; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; import org.neo4j.driver.summary.ResultSummary; class InternalExecutableQueryTest { diff --git a/driver/src/test/java/org/neo4j/driver/internal/InternalResultTest.java b/driver/src/test/java/org/neo4j/driver/internal/InternalResultTest.java index 287b2a16bc..e24911c95a 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/InternalResultTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/InternalResultTest.java @@ -41,6 +41,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.BoltServerAddress; +import org.neo4j.bolt.connection.summary.RunSummary; import org.neo4j.driver.Query; import org.neo4j.driver.Record; import org.neo4j.driver.Result; @@ -50,9 +53,6 @@ import org.neo4j.driver.exceptions.ResultConsumedException; import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnection; import org.neo4j.driver.internal.adaptedbolt.summary.PullSummary; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; import org.neo4j.driver.internal.cursor.DisposableResultCursorImpl; import org.neo4j.driver.internal.cursor.ResultCursorImpl; import org.neo4j.driver.internal.value.NullValue; diff --git a/driver/src/test/java/org/neo4j/driver/internal/InternalSessionTest.java b/driver/src/test/java/org/neo4j/driver/internal/InternalSessionTest.java index 170ceefc5a..89257bf95f 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/InternalSessionTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/InternalSessionTest.java @@ -33,13 +33,13 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.ArgumentMatcher; +import org.neo4j.bolt.connection.TelemetryApi; import org.neo4j.driver.Session; import org.neo4j.driver.TransactionCallback; import org.neo4j.driver.TransactionConfig; import org.neo4j.driver.TransactionContext; import org.neo4j.driver.internal.async.NetworkSession; import org.neo4j.driver.internal.async.UnmanagedTransaction; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; import org.neo4j.driver.internal.retry.RetryLogic; import org.neo4j.driver.internal.telemetry.ApiTelemetryWork; diff --git a/driver/src/test/java/org/neo4j/driver/internal/InternalTransactionTest.java b/driver/src/test/java/org/neo4j/driver/internal/InternalTransactionTest.java index 9dd7faa87e..3c8b0c130e 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/InternalTransactionTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/InternalTransactionTest.java @@ -46,6 +46,10 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.stubbing.Answer; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.summary.BeginSummary; +import org.neo4j.bolt.connection.summary.CommitSummary; +import org.neo4j.bolt.connection.summary.RollbackSummary; import org.neo4j.driver.Query; import org.neo4j.driver.Result; import org.neo4j.driver.Transaction; @@ -53,10 +57,6 @@ import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnection; import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnectionProvider; import org.neo4j.driver.internal.adaptedbolt.DriverResponseHandler; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.CommitSummary; -import org.neo4j.driver.internal.bolt.api.summary.RollbackSummary; import org.neo4j.driver.internal.value.IntegerValue; class InternalTransactionTest { diff --git a/driver/src/test/java/org/neo4j/driver/internal/adaptedbolt/ErrorMapperTest.java b/driver/src/test/java/org/neo4j/driver/internal/adaptedbolt/ErrorMapperTest.java index b23438fa4a..61cc1cb8a7 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/adaptedbolt/ErrorMapperTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/adaptedbolt/ErrorMapperTest.java @@ -24,6 +24,8 @@ import java.util.Collections; import javax.net.ssl.SSLHandshakeException; import org.junit.jupiter.api.Test; +import org.neo4j.bolt.connection.GqlStatusError; +import org.neo4j.bolt.connection.exception.BoltFailureException; import org.neo4j.driver.exceptions.AuthenticationException; import org.neo4j.driver.exceptions.AuthorizationExpiredException; import org.neo4j.driver.exceptions.ClientException; @@ -32,8 +34,6 @@ import org.neo4j.driver.exceptions.SecurityException; import org.neo4j.driver.exceptions.TokenExpiredException; import org.neo4j.driver.exceptions.TransientException; -import org.neo4j.driver.internal.bolt.api.GqlStatusError; -import org.neo4j.driver.internal.bolt.api.exception.BoltFailureException; class ErrorMapperTest { private BoltFailureException newError(String code, String message) { diff --git a/driver/src/test/java/org/neo4j/driver/internal/async/InternalAsyncSessionTest.java b/driver/src/test/java/org/neo4j/driver/internal/async/InternalAsyncSessionTest.java index 44caee6094..bddb3892db 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/async/InternalAsyncSessionTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/async/InternalAsyncSessionTest.java @@ -64,6 +64,10 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.stubbing.Answer; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.DatabaseName; +import org.neo4j.bolt.connection.summary.BeginSummary; +import org.neo4j.bolt.connection.summary.RollbackSummary; import org.neo4j.driver.AccessMode; import org.neo4j.driver.Query; import org.neo4j.driver.TransactionConfig; @@ -80,10 +84,6 @@ import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnection; import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnectionProvider; import org.neo4j.driver.internal.adaptedbolt.DriverResponseHandler; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.RollbackSummary; import org.neo4j.driver.internal.retry.RetryLogic; import org.neo4j.driver.internal.util.FixedRetryLogic; import org.neo4j.driver.internal.value.IntegerValue; diff --git a/driver/src/test/java/org/neo4j/driver/internal/async/InternalAsyncTransactionTest.java b/driver/src/test/java/org/neo4j/driver/internal/async/InternalAsyncTransactionTest.java index 3447841f1d..d6d5bdd026 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/async/InternalAsyncTransactionTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/async/InternalAsyncTransactionTest.java @@ -49,6 +49,12 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.stubbing.Answer; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.DatabaseName; +import org.neo4j.bolt.connection.summary.BeginSummary; +import org.neo4j.bolt.connection.summary.CommitSummary; +import org.neo4j.bolt.connection.summary.RollbackSummary; +import org.neo4j.bolt.connection.summary.RunSummary; import org.neo4j.driver.Query; import org.neo4j.driver.Value; import org.neo4j.driver.async.AsyncTransaction; @@ -58,12 +64,6 @@ import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnection; import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnectionProvider; import org.neo4j.driver.internal.adaptedbolt.summary.PullSummary; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.CommitSummary; -import org.neo4j.driver.internal.bolt.api.summary.RollbackSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; import org.neo4j.driver.internal.value.IntegerValue; class InternalAsyncTransactionTest { diff --git a/driver/src/test/java/org/neo4j/driver/internal/async/LeakLoggingNetworkSessionTest.java b/driver/src/test/java/org/neo4j/driver/internal/async/LeakLoggingNetworkSessionTest.java index 1f6d125462..1a60b15293 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/async/LeakLoggingNetworkSessionTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/async/LeakLoggingNetworkSessionTest.java @@ -28,8 +28,8 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.neo4j.bolt.connection.DatabaseNameUtil.defaultDatabase; import static org.neo4j.driver.AccessMode.READ; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; import static org.neo4j.driver.testutil.TestUtil.setupConnectionAnswers; import java.util.Collections; @@ -38,6 +38,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; import org.mockito.ArgumentCaptor; +import org.neo4j.bolt.connection.TelemetryApi; +import org.neo4j.bolt.connection.summary.BeginSummary; +import org.neo4j.bolt.connection.summary.RunSummary; import org.neo4j.driver.AuthTokenManagers; import org.neo4j.driver.AuthTokens; import org.neo4j.driver.BookmarkManager; @@ -49,9 +52,6 @@ import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnection; import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnectionProvider; import org.neo4j.driver.internal.adaptedbolt.summary.PullSummary; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; import org.neo4j.driver.internal.security.BoltSecurityPlanManager; import org.neo4j.driver.internal.telemetry.ApiTelemetryWork; import org.neo4j.driver.internal.util.FixedRetryLogic; diff --git a/driver/src/test/java/org/neo4j/driver/internal/async/NetworkSessionTest.java b/driver/src/test/java/org/neo4j/driver/internal/async/NetworkSessionTest.java index a99c59b8a2..6cab96aa21 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/async/NetworkSessionTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/async/NetworkSessionTest.java @@ -61,6 +61,13 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import org.mockito.stubbing.Answer; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.DatabaseName; +import org.neo4j.bolt.connection.TelemetryApi; +import org.neo4j.bolt.connection.summary.BeginSummary; +import org.neo4j.bolt.connection.summary.ResetSummary; +import org.neo4j.bolt.connection.summary.RollbackSummary; +import org.neo4j.bolt.connection.summary.RunSummary; import org.neo4j.driver.AccessMode; import org.neo4j.driver.Query; import org.neo4j.driver.TransactionConfig; @@ -70,13 +77,6 @@ import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnectionProvider; import org.neo4j.driver.internal.adaptedbolt.DriverResponseHandler; import org.neo4j.driver.internal.adaptedbolt.summary.PullSummary; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.DatabaseName; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.ResetSummary; -import org.neo4j.driver.internal.bolt.api.summary.RollbackSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; import org.neo4j.driver.internal.telemetry.ApiTelemetryWork; import org.neo4j.driver.internal.util.FixedRetryLogic; @@ -420,13 +420,13 @@ void accessModeUsedToAcquireWriteConnections() { private void accessModeUsedToAcquireConnections(AccessMode mode) { var session2 = newSession(connectionProvider, mode); beginTransaction(session2); - var argument = ArgumentCaptor.forClass(org.neo4j.driver.internal.bolt.api.AccessMode.class); + var argument = ArgumentCaptor.forClass(org.neo4j.bolt.connection.AccessMode.class); verify(connectionProvider) .connect(any(), any(), any(), argument.capture(), any(), any(), any(), any(), any(), any()); assertEquals( switch (mode) { - case READ -> org.neo4j.driver.internal.bolt.api.AccessMode.READ; - case WRITE -> org.neo4j.driver.internal.bolt.api.AccessMode.WRITE; + case READ -> org.neo4j.bolt.connection.AccessMode.READ; + case WRITE -> org.neo4j.bolt.connection.AccessMode.WRITE; }, argument.getValue()); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/async/UnmanagedTransactionTest.java b/driver/src/test/java/org/neo4j/driver/internal/async/UnmanagedTransactionTest.java index 779f63c86a..3907298a32 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/async/UnmanagedTransactionTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/async/UnmanagedTransactionTest.java @@ -53,6 +53,15 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.neo4j.bolt.connection.AccessMode; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.DatabaseNameUtil; +import org.neo4j.bolt.connection.TelemetryApi; +import org.neo4j.bolt.connection.summary.BeginSummary; +import org.neo4j.bolt.connection.summary.CommitSummary; +import org.neo4j.bolt.connection.summary.ResetSummary; +import org.neo4j.bolt.connection.summary.RollbackSummary; +import org.neo4j.bolt.connection.summary.RunSummary; import org.neo4j.driver.Bookmark; import org.neo4j.driver.Logging; import org.neo4j.driver.Query; @@ -66,15 +75,6 @@ import org.neo4j.driver.internal.InternalBookmark; import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnection; import org.neo4j.driver.internal.adaptedbolt.summary.PullSummary; -import org.neo4j.driver.internal.bolt.api.AccessMode; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.DatabaseNameUtil; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; -import org.neo4j.driver.internal.bolt.api.summary.BeginSummary; -import org.neo4j.driver.internal.bolt.api.summary.CommitSummary; -import org.neo4j.driver.internal.bolt.api.summary.ResetSummary; -import org.neo4j.driver.internal.bolt.api.summary.RollbackSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; import org.neo4j.driver.internal.telemetry.ApiTelemetryWork; class UnmanagedTransactionTest { diff --git a/driver/src/test/java/org/neo4j/driver/internal/cursor/ResultCursorImplTest.java b/driver/src/test/java/org/neo4j/driver/internal/cursor/ResultCursorImplTest.java index 16525016a5..0d602a08ad 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/cursor/ResultCursorImplTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/cursor/ResultCursorImplTest.java @@ -37,6 +37,9 @@ import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.stubbing.Answer; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.BoltServerAddress; +import org.neo4j.bolt.connection.summary.RunSummary; import org.neo4j.driver.Query; import org.neo4j.driver.Value; import org.neo4j.driver.exceptions.Neo4jException; @@ -45,9 +48,6 @@ import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnection; import org.neo4j.driver.internal.adaptedbolt.DriverResponseHandler; import org.neo4j.driver.internal.adaptedbolt.summary.PullSummary; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; class ResultCursorImplTest { ResultCursorImpl cursor; diff --git a/driver/src/test/java/org/neo4j/driver/internal/cursor/RxResultCursorImplTest.java b/driver/src/test/java/org/neo4j/driver/internal/cursor/RxResultCursorImplTest.java index 470986f13d..be01917746 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/cursor/RxResultCursorImplTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/cursor/RxResultCursorImplTest.java @@ -33,14 +33,14 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Mock; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.BoltServerAddress; +import org.neo4j.bolt.connection.summary.RunSummary; import org.neo4j.driver.Logging; import org.neo4j.driver.Query; import org.neo4j.driver.Record; import org.neo4j.driver.internal.DatabaseBookmark; import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnection; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; class RxResultCursorImplTest { @Mock diff --git a/driver/src/test/java/org/neo4j/driver/internal/homedb/HomeDatabaseCacheImplTest.java b/driver/src/test/java/org/neo4j/driver/internal/homedb/HomeDatabaseCacheImplTest.java index 59600b455e..92975eff70 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/homedb/HomeDatabaseCacheImplTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/homedb/HomeDatabaseCacheImplTest.java @@ -25,7 +25,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Mock; -import org.neo4j.driver.internal.bolt.api.BoltConnection; +import org.neo4j.bolt.connection.BoltConnection; class HomeDatabaseCacheImplTest { HomeDatabaseCacheImpl cache; diff --git a/driver/src/test/java/org/neo4j/driver/internal/metrics/MicrometerConnectionPoolMetricsTest.java b/driver/src/test/java/org/neo4j/driver/internal/metrics/MicrometerConnectionPoolMetricsTest.java index 9b8ecbe679..589b6043f7 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/metrics/MicrometerConnectionPoolMetricsTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/metrics/MicrometerConnectionPoolMetricsTest.java @@ -28,9 +28,9 @@ import java.util.function.IntSupplier; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.neo4j.bolt.connection.BoltServerAddress; +import org.neo4j.bolt.connection.ListenerEvent; import org.neo4j.driver.ConnectionPoolMetrics; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.ListenerEvent; class MicrometerConnectionPoolMetricsTest { static final String ID = "id"; diff --git a/driver/src/test/java/org/neo4j/driver/internal/metrics/MicrometerMetricsTest.java b/driver/src/test/java/org/neo4j/driver/internal/metrics/MicrometerMetricsTest.java index 29fd350913..231aad6c75 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/metrics/MicrometerMetricsTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/metrics/MicrometerMetricsTest.java @@ -26,9 +26,9 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import org.neo4j.bolt.connection.BoltServerAddress; +import org.neo4j.bolt.connection.ListenerEvent; import org.neo4j.driver.ConnectionPoolMetrics; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.ListenerEvent; class MicrometerMetricsTest { static final String ID = "id"; diff --git a/driver/src/test/java/org/neo4j/driver/internal/reactive/InternalReactiveSessionTest.java b/driver/src/test/java/org/neo4j/driver/internal/reactive/InternalReactiveSessionTest.java index 752c86b719..79a60a4082 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/reactive/InternalReactiveSessionTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/reactive/InternalReactiveSessionTest.java @@ -51,6 +51,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import org.neo4j.bolt.connection.TelemetryApi; import org.neo4j.driver.AccessMode; import org.neo4j.driver.Bookmark; import org.neo4j.driver.Query; @@ -59,7 +60,6 @@ import org.neo4j.driver.internal.InternalRecord; import org.neo4j.driver.internal.async.NetworkSession; import org.neo4j.driver.internal.async.UnmanagedTransaction; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; import org.neo4j.driver.internal.cursor.RxResultCursor; import org.neo4j.driver.internal.cursor.RxResultCursorImpl; import org.neo4j.driver.internal.retry.RetryLogic; diff --git a/driver/src/test/java/org/neo4j/driver/internal/reactive/InternalRxResultTest.java b/driver/src/test/java/org/neo4j/driver/internal/reactive/InternalRxResultTest.java index 1b68f6a002..a6264008c1 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/reactive/InternalRxResultTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/reactive/InternalRxResultTest.java @@ -43,14 +43,14 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.mockito.stubbing.Answer; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.BoltServerAddress; +import org.neo4j.bolt.connection.summary.RunSummary; import org.neo4j.driver.Logging; import org.neo4j.driver.Record; import org.neo4j.driver.internal.InternalRecord; import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnection; import org.neo4j.driver.internal.adaptedbolt.DriverResponseHandler; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; import org.neo4j.driver.internal.cursor.RxResultCursor; import org.neo4j.driver.internal.cursor.RxResultCursorImpl; import org.neo4j.driver.internal.util.Futures; diff --git a/driver/src/test/java/org/neo4j/driver/internal/reactive/InternalRxSessionTest.java b/driver/src/test/java/org/neo4j/driver/internal/reactive/InternalRxSessionTest.java index 942f89ff91..7681e06ff5 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/reactive/InternalRxSessionTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/reactive/InternalRxSessionTest.java @@ -42,6 +42,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import org.neo4j.bolt.connection.TelemetryApi; import org.neo4j.driver.AccessMode; import org.neo4j.driver.Query; import org.neo4j.driver.TransactionConfig; @@ -49,7 +50,6 @@ import org.neo4j.driver.internal.InternalRecord; import org.neo4j.driver.internal.async.NetworkSession; import org.neo4j.driver.internal.async.UnmanagedTransaction; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; import org.neo4j.driver.internal.cursor.RxResultCursor; import org.neo4j.driver.internal.cursor.RxResultCursorImpl; import org.neo4j.driver.internal.telemetry.ApiTelemetryWork; diff --git a/driver/src/test/java/org/neo4j/driver/internal/telemetry/ApiTelemetryWorkTest.java b/driver/src/test/java/org/neo4j/driver/internal/telemetry/ApiTelemetryWorkTest.java index b0462bc306..1c04cf17e2 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/telemetry/ApiTelemetryWorkTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/telemetry/ApiTelemetryWorkTest.java @@ -25,8 +25,8 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import org.mockito.Mockito; +import org.neo4j.bolt.connection.TelemetryApi; import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnection; -import org.neo4j.driver.internal.bolt.api.TelemetryApi; class ApiTelemetryWorkTest { diff --git a/driver/src/test/java/org/neo4j/driver/internal/util/MetadataExtractorTest.java b/driver/src/test/java/org/neo4j/driver/internal/util/MetadataExtractorTest.java index 4eb7be7cfd..e82cc799f1 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/util/MetadataExtractorTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/util/MetadataExtractorTest.java @@ -41,6 +41,8 @@ import java.util.Map; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Test; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.BoltServerAddress; import org.neo4j.driver.NotificationCategory; import org.neo4j.driver.NotificationSeverity; import org.neo4j.driver.Query; @@ -48,8 +50,6 @@ import org.neo4j.driver.Values; import org.neo4j.driver.exceptions.value.Uncoercible; import org.neo4j.driver.internal.adaptedbolt.DriverBoltConnection; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; import org.neo4j.driver.internal.summary.InternalInputPosition; import org.neo4j.driver.summary.Notification; import org.neo4j.driver.summary.ResultSummary; diff --git a/driver/src/test/java/org/neo4j/driver/testutil/DatabaseExtension.java b/driver/src/test/java/org/neo4j/driver/testutil/DatabaseExtension.java index 5729d02d69..ad44f68d81 100644 --- a/driver/src/test/java/org/neo4j/driver/testutil/DatabaseExtension.java +++ b/driver/src/test/java/org/neo4j/driver/testutil/DatabaseExtension.java @@ -39,13 +39,13 @@ import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.extension.ExtensionContext; +import org.neo4j.bolt.connection.BoltServerAddress; import org.neo4j.driver.AuthToken; import org.neo4j.driver.AuthTokenManager; import org.neo4j.driver.AuthTokens; import org.neo4j.driver.Config; import org.neo4j.driver.Driver; import org.neo4j.driver.GraphDatabase; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; import org.neo4j.driver.internal.security.StaticAuthTokenManager; import org.neo4j.driver.testutil.CertificateUtil.CertificateKeyPair; import org.testcontainers.DockerClientFactory; diff --git a/driver/src/test/java/org/neo4j/driver/testutil/TestUtil.java b/driver/src/test/java/org/neo4j/driver/testutil/TestUtil.java index 7a39eae0d9..1d7891d033 100644 --- a/driver/src/test/java/org/neo4j/driver/testutil/TestUtil.java +++ b/driver/src/test/java/org/neo4j/driver/testutil/TestUtil.java @@ -29,9 +29,9 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.neo4j.bolt.connection.DatabaseNameUtil.defaultDatabase; import static org.neo4j.driver.AccessMode.WRITE; import static org.neo4j.driver.SessionConfig.forDatabase; -import static org.neo4j.driver.internal.bolt.api.DatabaseNameUtil.defaultDatabase; import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING; import io.netty.util.internal.PlatformDependent; @@ -60,6 +60,10 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.mockito.verification.VerificationMode; +import org.neo4j.bolt.connection.BoltProtocolVersion; +import org.neo4j.bolt.connection.BoltServerAddress; +import org.neo4j.bolt.connection.summary.CommitSummary; +import org.neo4j.bolt.connection.summary.RunSummary; import org.neo4j.driver.AccessMode; import org.neo4j.driver.AuthTokenManager; import org.neo4j.driver.Bookmark; @@ -74,10 +78,6 @@ import org.neo4j.driver.internal.adaptedbolt.DriverResponseHandler; import org.neo4j.driver.internal.adaptedbolt.summary.PullSummary; import org.neo4j.driver.internal.async.NetworkSession; -import org.neo4j.driver.internal.bolt.api.BoltProtocolVersion; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.summary.CommitSummary; -import org.neo4j.driver.internal.bolt.api.summary.RunSummary; import org.neo4j.driver.internal.retry.RetryLogic; import org.neo4j.driver.internal.security.BoltSecurityPlanManager; import org.neo4j.driver.internal.util.FixedRetryLogic; diff --git a/examples/LICENSES.txt b/examples/LICENSES.txt index f33622e81c..3d838254bd 100644 --- a/examples/LICENSES.txt +++ b/examples/LICENSES.txt @@ -4,6 +4,10 @@ libraries. For an overview of the licenses see the NOTICE.txt file. ------------------------------------------------------------------------------ Apache Software License, Version 2.0 + Neo4j Bolt Connection (Netty reference impl) + Neo4j Bolt Connection (Pooled provider impl) + Neo4j Bolt Connection (Provider SPI) + Neo4j Bolt Connection (Routed provider impl) Netty/Buffer Netty/Codec Netty/Common diff --git a/examples/NOTICE.txt b/examples/NOTICE.txt index ee07af014f..be72589619 100644 --- a/examples/NOTICE.txt +++ b/examples/NOTICE.txt @@ -19,6 +19,10 @@ Third-party licenses -------------------- Apache Software License, Version 2.0 + Neo4j Bolt Connection (Netty reference impl) + Neo4j Bolt Connection (Pooled provider impl) + Neo4j Bolt Connection (Provider SPI) + Neo4j Bolt Connection (Routed provider impl) Netty/Buffer Netty/Codec Netty/Common diff --git a/pom.xml b/pom.xml index 925da85b82..341f1a4a03 100644 --- a/pom.xml +++ b/pom.xml @@ -32,6 +32,7 @@ true + 1.0.0 1.0.4 @@ -67,11 +68,6 @@ - bolt-api - bolt-api-test-values - bolt-api-netty - bolt-api-pooled - bolt-api-routed driver bundle examples @@ -106,6 +102,13 @@ + + org.neo4j.bolt + neo4j-bolt-connection-bom + ${neo4j-bolt-connection-bom.version} + pom + import + org.reactivestreams reactive-streams @@ -225,12 +228,6 @@ pom import - - com.tngtech.archunit - archunit-junit5 - ${archunit-junit5.version} - test - diff --git a/testkit-backend/LICENSES.txt b/testkit-backend/LICENSES.txt index ef04ce5961..aa001d723c 100644 --- a/testkit-backend/LICENSES.txt +++ b/testkit-backend/LICENSES.txt @@ -7,6 +7,10 @@ Apache Software License, Version 2.0 Jackson-annotations Jackson-core jackson-databind + Neo4j Bolt Connection (Netty reference impl) + Neo4j Bolt Connection (Pooled provider impl) + Neo4j Bolt Connection (Provider SPI) + Neo4j Bolt Connection (Routed provider impl) Netty/Buffer Netty/Codec Netty/Common diff --git a/testkit-backend/NOTICE.txt b/testkit-backend/NOTICE.txt index e80f601d59..71a12aa82e 100644 --- a/testkit-backend/NOTICE.txt +++ b/testkit-backend/NOTICE.txt @@ -22,6 +22,10 @@ Apache Software License, Version 2.0 Jackson-annotations Jackson-core jackson-databind + Neo4j Bolt Connection (Netty reference impl) + Neo4j Bolt Connection (Pooled provider impl) + Neo4j Bolt Connection (Provider SPI) + Neo4j Bolt Connection (Routed provider impl) Netty/Buffer Netty/Codec Netty/Common diff --git a/testkit-backend/pom.xml b/testkit-backend/pom.xml index 052d47ea98..e615682bf6 100644 --- a/testkit-backend/pom.xml +++ b/testkit-backend/pom.xml @@ -27,30 +27,6 @@ neo4j-java-driver ${project.version} - - org.neo4j.driver - neo4j-bolt-api - ${project.version} - true - - - org.neo4j.driver - neo4j-bolt-api-netty - ${project.version} - true - - - org.neo4j.driver - neo4j-bolt-api-pooled - ${project.version} - true - - - org.neo4j.driver - neo4j-bolt-api-routed - ${project.version} - true - io.netty netty-handler diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/TestkitState.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/TestkitState.java index e57c84588c..be81d585ca 100644 --- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/TestkitState.java +++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/TestkitState.java @@ -41,11 +41,11 @@ import neo4j.org.testkit.backend.holder.TransactionHolder; import neo4j.org.testkit.backend.messages.requests.TestkitCallbackResult; import neo4j.org.testkit.backend.messages.responses.TestkitResponse; +import org.neo4j.bolt.connection.routed.impl.cluster.RoutingTableRegistry; import org.neo4j.driver.AuthTokenManager; import org.neo4j.driver.BookmarkManager; import org.neo4j.driver.ClientCertificateManager; import org.neo4j.driver.Logging; -import org.neo4j.driver.internal.bolt.routedimpl.impl.cluster.RoutingTableRegistry; import reactor.core.publisher.Mono; public class TestkitState { diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/GetConnectionPoolMetrics.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/GetConnectionPoolMetrics.java index bef1a6c116..1b3ea5f8b4 100644 --- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/GetConnectionPoolMetrics.java +++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/GetConnectionPoolMetrics.java @@ -24,7 +24,7 @@ import neo4j.org.testkit.backend.TestkitState; import neo4j.org.testkit.backend.messages.responses.ConnectionPoolMetrics; import neo4j.org.testkit.backend.messages.responses.TestkitResponse; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; +import org.neo4j.bolt.connection.BoltServerAddress; import reactor.core.publisher.Mono; @Getter diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/GetRoutingTable.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/GetRoutingTable.java index 78e5bdf122..cb59015b60 100644 --- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/GetRoutingTable.java +++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/GetRoutingTable.java @@ -26,8 +26,8 @@ import neo4j.org.testkit.backend.TestkitState; import neo4j.org.testkit.backend.messages.responses.RoutingTable; import neo4j.org.testkit.backend.messages.responses.TestkitResponse; -import org.neo4j.driver.internal.bolt.api.BoltServerAddress; -import org.neo4j.driver.internal.bolt.api.DatabaseNameUtil; +import org.neo4j.bolt.connection.BoltServerAddress; +import org.neo4j.bolt.connection.DatabaseNameUtil; import reactor.core.publisher.Mono; @Setter diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewDriver.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewDriver.java index c5c62ef9f4..8ccfb1169d 100644 --- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewDriver.java +++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewDriver.java @@ -44,6 +44,8 @@ import neo4j.org.testkit.backend.messages.responses.ResolverResolutionRequired; import neo4j.org.testkit.backend.messages.responses.TestkitCallback; import neo4j.org.testkit.backend.messages.responses.TestkitResponse; +import org.neo4j.bolt.connection.DefaultDomainNameResolver; +import org.neo4j.bolt.connection.DomainNameResolver; import org.neo4j.driver.AuthTokenManager; import org.neo4j.driver.ClientCertificateManager; import org.neo4j.driver.ClientCertificateManagers; @@ -54,8 +56,6 @@ import org.neo4j.driver.internal.InternalNotificationSeverity; import org.neo4j.driver.internal.InternalServerAddress; import org.neo4j.driver.internal.SecuritySettings; -import org.neo4j.driver.internal.bolt.api.DefaultDomainNameResolver; -import org.neo4j.driver.internal.bolt.api.DomainNameResolver; import org.neo4j.driver.internal.security.BoltSecurityPlanManager; import org.neo4j.driver.internal.security.SecurityPlans; import org.neo4j.driver.internal.security.StaticAuthTokenManager;